http-sankhya 1.0.2 → 1.0.4

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
@@ -44,7 +44,7 @@ await sankhya.login();
44
44
 
45
45
  ### 1. loadRecords (Buscar Múltiplos Registros)
46
46
 
47
- Busca uma lista de registros com suporte a filtros, paginação e seleção de campos.
47
+ Busca uma lista de registros com suporte a filtros, paginação e seleção de campos. Este método utiliza o serviço `CRUDServiceProvider.loadRecords`.
48
48
 
49
49
  #### Exemplo Básico
50
50
  ```typescript
@@ -54,6 +54,12 @@ const produtos = await sankhya.loadRecords({
54
54
  expression: "ATIVO = 'S'" // Filtro SQL-like
55
55
  }
56
56
  });
57
+
58
+ // Retorno Exemplo:
59
+ // [
60
+ // { "CODGRUPOPROD": "100", "DESCRGRUPOPROD": "GERAL", "ATIVO": "S" },
61
+ // { "CODGRUPOPROD": "101", "DESCRGRUPOPROD": "MATERIA PRIMA", "ATIVO": "S" }
62
+ // ]
57
63
  ```
58
64
 
59
65
  #### Exemplo com Paginação e Seleção de Campos
@@ -72,6 +78,12 @@ const parceiros = await sankhya.loadRecords({
72
78
  }
73
79
  }
74
80
  });
81
+
82
+ // Retorno Exemplo:
83
+ // [
84
+ // { "CODPARC": "200", "NOMEPARC": "CLIENTE EXEMPLO", "CGC_CPF": "123.456.789-00", "EMAIL": "cliente@email.com" },
85
+ // { "CODPARC": "201", "NOMEPARC": "OUTRO CLIENTE", "CGC_CPF": "987.654.321-00", "EMAIL": "outro@email.com" }
86
+ // ]
75
87
  ```
76
88
 
77
89
  #### Exemplo com Campos de Apresentação
@@ -85,13 +97,23 @@ const vendas = await sankhya.loadRecords({
85
97
  expression: "DTNEG >= '01/01/2024'"
86
98
  }
87
99
  });
100
+
101
+ // Retorno Exemplo:
102
+ // [
103
+ // {
104
+ // "NUNOTA": "100",
105
+ // "DTNEG": "01/01/2024",
106
+ // "CODPARC": "200",
107
+ // "Parceiro_NOMEPARC": "CLIENTE EXEMPLO"
108
+ // }
109
+ // ]
88
110
  ```
89
111
 
90
112
  ---
91
113
 
92
114
  ### 2. loadRecord (Buscar Registro Único)
93
115
 
94
- Busca um único registro específico, geralmente pela Chave Primária (PK).
116
+ Busca um único registro específico, geralmente pela Chave Primária (PK). Este método utiliza o serviço `CRUDServiceProvider.loadRecord`.
95
117
 
96
118
  ```typescript
97
119
  const produto = await sankhya.loadRecord({
@@ -110,13 +132,21 @@ const produto = await sankhya.loadRecord({
110
132
 
111
133
  console.log(produto);
112
134
  // Saída: { CODPROD: "1005", DESCRPROD: "PRODUTO TESTE", ... }
135
+
136
+ // Retorno Exemplo Completo:
137
+ // {
138
+ // "CODPROD": "1005",
139
+ // "DESCRPROD": "PRODUTO TESTE",
140
+ // "ATIVO": "S",
141
+ // "PRECO": "50.00"
142
+ // }
113
143
  ```
114
144
 
115
145
  ---
116
146
 
117
147
  ### 3. saveRecord (Criar ou Atualizar Registro)
118
148
 
119
- Cria ou atualiza registros. A biblioteca formata automaticamente o payload do objeto `localFields` para o padrão exigido pelo Sankhya.
149
+ Cria ou atualiza registros. Este método é específico para manipulações que utilizam o serviço `CRUDServiceProvider.saveRecord`. A biblioteca formata automaticamente o payload do objeto `localFields` para o padrão exigido pelo Sankhya.
120
150
 
121
151
  #### Criar Novo Registro
122
152
  Para criar, omita a Chave Primária (se for auto-incremental) ou passe os valores necessários.
@@ -136,31 +166,63 @@ const novoGrupo = await sankhya.saveRecord({
136
166
  }
137
167
  }
138
168
  });
169
+
170
+ // Retorno Exemplo:
171
+ // {
172
+ // "CODGRUPOPROD": "161000",
173
+ // "DESCRGRUPOPROD": "NOVO GRUPO 2024"
174
+ // }
139
175
  ```
140
176
 
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).
177
+ #### Atualizar Registro Existente
178
+ Para atualizar um registro existente, você deve fornecer a propriedade `key` contendo a chave primária do registro. Isso instrui o Sankhya a realizar um update na linha específica.
143
179
 
144
180
  ```typescript
145
181
  const atualizacao = await sankhya.saveRecord({
146
182
  rootEntity: 'GrupoProduto',
147
183
  localFields: {
148
- CODGRUPOPROD: "20310006", // PK existente
149
- DESCRGRUPOPROD: "NOME ATUALIZADO", // Campo a alterar
184
+ DESCRGRUPOPROD: "NOME ATUALIZADO", // Campos a alterar
150
185
  ATIVO: "N"
186
+ },
187
+ key: {
188
+ CODGRUPOPROD: "20310006" // Chave Primária (PK) para identificação do registro
151
189
  }
152
190
  });
191
+
192
+ #### Retorno Exemplo (Sucesso)
193
+ Tanto na criação quanto na atualização, a biblioteca processa a resposta e retorna um objeto limpo com os campos solicitados no `fieldset`.
194
+
195
+ ```json
196
+ {
197
+ "CODGRUPOPROD": "160700",
198
+ "DESCRGRUPOPROD": "NOME ATUALIZADO",
199
+ "ATIVO": "N"
200
+ }
201
+ ```
202
+
203
+ #### Retorno Exemplo (Falha)
204
+ Caso ocorra algum erro (status '0'), a biblioteca retorna o objeto de resposta original contendo a mensagem de erro.
205
+
206
+ ```json
207
+ {
208
+ "serviceName": "CRUDServiceProvider.saveRecord",
209
+ "status": "0",
210
+ "pendingPrinting": "false",
211
+ "transactionId": "123456789",
212
+ "statusMessage": "Erro: O registro já existe ou violação de restrição de integridade."
213
+ }
214
+ ```
153
215
  ```
154
216
 
155
217
  ---
156
218
 
157
- ### 4. Execução de Serviço Genérico (execService)
219
+ ### 4. Execução de Serviço Mge (execServiceMge)
158
220
 
159
- Para endpoints que não sejam CRUD padrão (ex: executar Stored Procedures, ações de workflow, ou consultas de metadados), use `execService`.
221
+ Para endpoints que não sejam CRUD padrão (ex: executar Stored Procedures, ações de workflow, ou consultas de metadados), use `execServiceMge`. Este método utiliza o endpoint `/gateway/v1/mge/service.sbr`.
160
222
 
161
223
  #### Exemplo: Consultar Estoque (Serviço Hipotético)
162
224
  ```typescript
163
- const estoque = await sankhya.execService({
225
+ const estoque = await sankhya.execServiceMge({
164
226
  serviceName: 'EstoqueSP.getEstoque',
165
227
  requestBody: {
166
228
  codProd: '1005',
@@ -173,7 +235,7 @@ const estoque = await sankhya.execService({
173
235
  Embora exista o método `.delete()`, algumas operações de exclusão no Sankhya são feitas via serviços específicos.
174
236
 
175
237
  ```typescript
176
- await sankhya.execService({
238
+ await sankhya.execServiceMge({
177
239
  serviceName: 'CRUDServiceProvider.removeRecord',
178
240
  requestBody: {
179
241
  entity: {
@@ -184,6 +246,83 @@ await sankhya.execService({
184
246
  }
185
247
  }
186
248
  });
249
+
250
+ // Retorno Exemplo:
251
+ // {
252
+ // "serviceName": "CRUDServiceProvider.removeRecord",
253
+ // "status": "1",
254
+ // "pendingPrinting": "false",
255
+ // "transactionId": "123456789",
256
+ // "responseBody": {}
257
+ // }
258
+ ```
259
+
260
+ ---
261
+
262
+ ### 5. Execução de Serviço MgeCom (execServiceMgeCom)
263
+
264
+ Para serviços diversos do Sankhya que utilizam o endpoint **mgecom** (`/gateway/v1/mgecom/service.sbr`), como inclusão de notas, operações comerciais, etc. Este método recebe o `serviceName` e o `requestBody` em **formato JSON simples** e transforma automaticamente todos os valores primitivos (strings/números) para o formato `{ "$": "valor" }` exigido pelo Sankhya.
265
+
266
+ > **Nota:** Diferente do `execServiceMge` que usa `/gateway/v1/mge/service.sbr`, este método envia as requisições para `/gateway/v1/mgecom/service.sbr`.
267
+
268
+ #### Exemplo: Incluir Pedido de Venda / Nota (CACSP.incluirNota)
269
+ ```typescript
270
+ const nota = await sankhya.execServiceMgeCom('CACSP.incluirNota', {
271
+ nota: {
272
+ cabecalho: {
273
+ CODPARC: "3",
274
+ DTNEG: "03/07/2023",
275
+ CODTIPOPER: "1718",
276
+ CODTIPVENDA: "34",
277
+ CODVEND: "0",
278
+ CODEMP: "15",
279
+ TIPMOV: "V", // V = Venda | C=Compra | D=Devolução | etc.
280
+ CODNAT: "10101002",
281
+ CODCENCUS: "10600200",
282
+ SERIE: "14"
283
+ },
284
+ itens: {
285
+ INFORMARPRECO: "True",
286
+ item: [
287
+ {
288
+ CODPROD: "6",
289
+ QTDNEG: "1",
290
+ CODLOCALORIG: "0",
291
+ CODVOL: "SV",
292
+ PERCDESC: "0",
293
+ VLRUNIT: "81.75"
294
+ }
295
+ ]
296
+ }
297
+ }
298
+ });
299
+ ```
300
+
301
+ A biblioteca transforma automaticamente o payload acima para o formato exigido pelo Sankhya antes do envio:
302
+
303
+ ```json
304
+ {
305
+ "serviceName": "CACSP.incluirNota",
306
+ "requestBody": {
307
+ "nota": {
308
+ "cabecalho": {
309
+ "CODPARC": { "$": "3" },
310
+ "DTNEG": { "$": "03/07/2023" },
311
+ "CODTIPOPER": { "$": "1718" }
312
+ },
313
+ "itens": {
314
+ "INFORMARPRECO": { "$": "True" },
315
+ "item": [
316
+ {
317
+ "CODPROD": { "$": "6" },
318
+ "QTDNEG": { "$": "1" },
319
+ "CODVOL": { "$": "SV" }
320
+ }
321
+ ]
322
+ }
323
+ }
324
+ }
325
+ }
187
326
  ```
188
327
 
189
328
  ## Funcionalidades
@@ -192,4 +331,5 @@ await sankhya.execService({
192
331
  - *LoadRecords*: Retorna `Array<Objeto>`.
193
332
  - *LoadRecord*: Retorna `Objeto` único (lida com ausência de metadados).
194
333
  - **Transformação de Payload**: O método `saveRecord` aceita objetos simples JS (ex: `{ CAMPO: "Valor" }`) e os converte automaticamente para `{ CAMPO: { "$": "Valor" } }`.
334
+ - **Transformação Profunda de Payload**: O método `execServiceMgeCom` transforma recursivamente todos os valores primitivos de um objeto JSON aninhado para o formato `{ "$": "valor" }`, incluindo arrays e sub-objetos.
195
335
  - **Tipagem TypeScript**: Suporte completo a interfaces para garantir segurança de tipo no desenvolvimento.
package/dist/Sankhya.d.ts CHANGED
@@ -16,6 +16,7 @@ export interface SaveRecordOptions {
16
16
  rootEntity: string;
17
17
  includePresentationFields?: 'S' | 'N';
18
18
  localFields?: Record<string, any>;
19
+ key?: Record<string, any>;
19
20
  entity?: Record<string, any>;
20
21
  }
21
22
  export interface ExecServiceOptions {
@@ -39,9 +40,51 @@ export declare class Sankhya {
39
40
  put(path: string, body?: Record<string, any>, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
40
41
  patch(path: string, body?: Record<string, any>, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
41
42
  delete(path: string, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
42
- execService(options: ExecServiceOptions, outputType?: 'json' | 'xml'): Promise<any>;
43
+ execServiceMge(options: ExecServiceOptions, outputType?: 'json' | 'xml'): Promise<any>;
43
44
  loadRecords({ rootEntity, includePresentationFields, offsetPage, criteria, entity }: LoadRecordsOptions, outputType?: 'json' | 'xml'): Promise<any>;
44
45
  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
+ saveRecord({ rootEntity, includePresentationFields, localFields, key, entity }: SaveRecordOptions, outputType?: 'json' | 'xml'): Promise<any>;
47
+ /**
48
+ * Executa serviços diversos do Sankhya via endpoint mgecom.
49
+ * Recebe o serviceName e o requestBody em formato JSON simples,
50
+ * transformando automaticamente todos os valores primitivos para { "$": "valor" }.
51
+ *
52
+ * Endpoint: /gateway/v1/mgecom/service.sbr
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // Exemplo: Inclusão de Pedido de Venda
57
+ * const nota = await sankhya.execServiceMgeCom('CACSP.incluirNota', {
58
+ * nota: {
59
+ * cabecalho: {
60
+ * CODPARC: "3",
61
+ * DTNEG: "03/07/2023",
62
+ * CODTIPOPER: "1718",
63
+ * CODTIPVENDA: "34",
64
+ * CODVEND: "0",
65
+ * CODEMP: "15",
66
+ * TIPMOV: "P",
67
+ * CODNAT: "10101002",
68
+ * CODCENCUS: "10600200",
69
+ * SERIE: "14"
70
+ * },
71
+ * itens: {
72
+ * INFORMARPRECO: "True",
73
+ * item: [
74
+ * {
75
+ * CODPROD: "6",
76
+ * QTDNEG: "1",
77
+ * CODLOCALORIG: "0",
78
+ * CODVOL: "SV",
79
+ * PERCDESC: "0",
80
+ * VLRUNIT: "81.75"
81
+ * }
82
+ * ]
83
+ * }
84
+ * }
85
+ * });
86
+ * ```
87
+ */
88
+ execServiceMgeCom(serviceName: string, requestBody: Record<string, any>, outputType?: 'json' | 'xml'): Promise<any>;
46
89
  private isEmptyObject;
47
90
  }
package/dist/Sankhya.js CHANGED
@@ -94,7 +94,7 @@ class Sankhya {
94
94
  return response.data;
95
95
  }
96
96
  // Sankhya Specific Methods
97
- async execService(options, outputType = 'json') {
97
+ async execServiceMge(options, outputType = 'json') {
98
98
  // Standard Sankhya Service URL pattern: /mge/service.sbr?serviceName=...&outputType=json
99
99
  const { serviceName, requestBody } = options;
100
100
  // Construct the wrapper expected by Sankhya JSON API
@@ -110,7 +110,7 @@ class Sankhya {
110
110
  }, {});
111
111
  }
112
112
  async loadRecords({ rootEntity, includePresentationFields = 'N', offsetPage = 0, criteria = {}, entity = {} }, outputType = 'json') {
113
- return this.execService({
113
+ return this.execServiceMge({
114
114
  serviceName: 'CRUDServiceProvider.loadRecords',
115
115
  requestBody: {
116
116
  dataSet: {
@@ -125,7 +125,7 @@ class Sankhya {
125
125
  }, outputType);
126
126
  }
127
127
  async loadRecord({ rootEntity, includePresentationFields = 'N', criteria = {}, entity = {}, rows = {} }, outputType = 'json') {
128
- return this.execService({
128
+ return this.execServiceMge({
129
129
  serviceName: 'CRUDServiceProvider.loadRecord',
130
130
  requestBody: {
131
131
  dataSet: {
@@ -139,15 +139,16 @@ class Sankhya {
139
139
  outputType
140
140
  }, outputType);
141
141
  }
142
- async saveRecord({ rootEntity, includePresentationFields = 'N', localFields = {}, entity = {} }, outputType = 'json') {
143
- return this.execService({
142
+ async saveRecord({ rootEntity, includePresentationFields = 'N', localFields = {}, key = {}, entity = {} }, outputType = 'json') {
143
+ return this.execServiceMge({
144
144
  serviceName: 'CRUDServiceProvider.saveRecord',
145
145
  requestBody: {
146
146
  dataSet: {
147
147
  rootEntity,
148
148
  includePresentationFields,
149
149
  dataRow: {
150
- localFields: SankhyaHelper_1.SankhyaHelper.transformLocalFields(localFields)
150
+ localFields: SankhyaHelper_1.SankhyaHelper.transformLocalFields(localFields),
151
+ key: SankhyaHelper_1.SankhyaHelper.transformLocalFields(key)
151
152
  },
152
153
  entity
153
154
  }
@@ -155,6 +156,58 @@ class Sankhya {
155
156
  outputType
156
157
  }, outputType);
157
158
  }
159
+ /**
160
+ * Executa serviços diversos do Sankhya via endpoint mgecom.
161
+ * Recebe o serviceName e o requestBody em formato JSON simples,
162
+ * transformando automaticamente todos os valores primitivos para { "$": "valor" }.
163
+ *
164
+ * Endpoint: /gateway/v1/mgecom/service.sbr
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * // Exemplo: Inclusão de Pedido de Venda
169
+ * const nota = await sankhya.execServiceMgeCom('CACSP.incluirNota', {
170
+ * nota: {
171
+ * cabecalho: {
172
+ * CODPARC: "3",
173
+ * DTNEG: "03/07/2023",
174
+ * CODTIPOPER: "1718",
175
+ * CODTIPVENDA: "34",
176
+ * CODVEND: "0",
177
+ * CODEMP: "15",
178
+ * TIPMOV: "P",
179
+ * CODNAT: "10101002",
180
+ * CODCENCUS: "10600200",
181
+ * SERIE: "14"
182
+ * },
183
+ * itens: {
184
+ * INFORMARPRECO: "True",
185
+ * item: [
186
+ * {
187
+ * CODPROD: "6",
188
+ * QTDNEG: "1",
189
+ * CODLOCALORIG: "0",
190
+ * CODVOL: "SV",
191
+ * PERCDESC: "0",
192
+ * VLRUNIT: "81.75"
193
+ * }
194
+ * ]
195
+ * }
196
+ * }
197
+ * });
198
+ * ```
199
+ */
200
+ async execServiceMgeCom(serviceName, requestBody, outputType = 'json') {
201
+ const transformedBody = SankhyaHelper_1.SankhyaHelper.transformDeepFields(requestBody);
202
+ const payload = {
203
+ serviceName,
204
+ requestBody: transformedBody
205
+ };
206
+ return this.post('/gateway/v1/mgecom/service.sbr', payload, {
207
+ serviceName,
208
+ outputType
209
+ }, {});
210
+ }
158
211
  isEmptyObject(obj) {
159
212
  return obj != null &&
160
213
  obj.constructor === Object &&
@@ -6,6 +6,12 @@ export declare class SankhyaHelper {
6
6
  static processResponse(response: any, options?: {
7
7
  serviceName?: string;
8
8
  }): any;
9
+ /**
10
+ * Transforma recursivamente todos os valores primitivos (string/number) de um objeto
11
+ * para o formato Sankhya { "$": valor }, percorrendo objetos e arrays aninhados.
12
+ * Ex: { nota: { cabecalho: { CAMPO: "VALOR" } } } -> { nota: { cabecalho: { CAMPO: { "$": "VALOR" } } } }
13
+ */
14
+ static transformDeepFields(obj: any): any;
9
15
  /**
10
16
  * Transforma um objeto simples de chave/valor para o formato do Sankhya
11
17
  * Ex: { CAMPO: "VALOR" } -> { CAMPO: { "$": "VALOR" } }
@@ -22,6 +22,37 @@ class SankhyaHelper {
22
22
  return response;
23
23
  }
24
24
  }
25
+ /**
26
+ * Transforma recursivamente todos os valores primitivos (string/number) de um objeto
27
+ * para o formato Sankhya { "$": valor }, percorrendo objetos e arrays aninhados.
28
+ * Ex: { nota: { cabecalho: { CAMPO: "VALOR" } } } -> { nota: { cabecalho: { CAMPO: { "$": "VALOR" } } } }
29
+ */
30
+ static transformDeepFields(obj) {
31
+ if (obj === null || obj === undefined) {
32
+ return obj;
33
+ }
34
+ // Se for string ou number, transforma para { "$": valor }
35
+ if (typeof obj === 'string' || typeof obj === 'number') {
36
+ return { $: String(obj) };
37
+ }
38
+ // Se for array, aplica recursivamente em cada elemento
39
+ if (Array.isArray(obj)) {
40
+ return obj.map(item => this.transformDeepFields(item));
41
+ }
42
+ // Se já estiver no formato { "$": ... }, mantém como está
43
+ if (typeof obj === 'object' && '$' in obj && Object.keys(obj).length === 1) {
44
+ return obj;
45
+ }
46
+ // Se for objeto, aplica recursivamente em cada propriedade
47
+ if (typeof obj === 'object') {
48
+ const transformed = {};
49
+ for (const key of Object.keys(obj)) {
50
+ transformed[key] = this.transformDeepFields(obj[key]);
51
+ }
52
+ return transformed;
53
+ }
54
+ return obj;
55
+ }
25
56
  /**
26
57
  * Transforma um objeto simples de chave/valor para o formato do Sankhya
27
58
  * Ex: { CAMPO: "VALOR" } -> { CAMPO: { "$": "VALOR" } }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "http-sankhya",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Biblioteca TypeScript para integração com ERP Sankhya",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",