sgp-sdk 2.0.0-beta.1 → 2.0.0-beta.2
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/CHANGELOG.md +147 -0
- package/COMPATIBILITY.md +161 -81
- package/MIGRATION.md +66 -5
- package/README.md +111 -69
- package/dist/client.d.ts +303 -26
- package/dist/constants.d.ts +13 -0
- package/dist/document.d.ts +11 -0
- package/dist/index.d.ts +13 -3
- package/dist/index.js +1510 -708
- package/dist/normalize.d.ts +9 -0
- package/dist/operation-sensitivity.d.ts +239 -6
- package/dist/operation.d.ts +7 -1
- package/dist/operations/contracts-check-connection.d.ts +56 -0
- package/dist/operations/contracts-list-services.d.ts +103 -0
- package/dist/operations/coverage-check-address.d.ts +46 -0
- package/dist/operations/coverage-check.d.ts +8 -7
- package/dist/operations/coverage-list-gateways.d.ts +16 -0
- package/dist/operations/crm-customers-create.d.ts +13 -3
- package/dist/operations/customers-list.d.ts +6 -0
- package/dist/operations/invoices-list.d.ts +11 -5
- package/dist/operations/maintenance-list.d.ts +35 -0
- package/dist/operations/occurrences-create.d.ts +10 -1
- package/dist/operations/occurrences-list.d.ts +127 -0
- package/dist/operations/pre-registrations-create.d.ts +29 -6
- package/dist/operations/pre-registrations-list-plans.d.ts +2 -2
- package/dist/operations/services-add-generic.d.ts +52 -0
- package/dist/operations/services-add-tv.d.ts +3 -3
- package/dist/operations/services-remove-generic.d.ts +28 -0
- package/dist/operations/services-remove-tv.d.ts +3 -3
- package/dist/operations/work-orders-get.d.ts +99 -0
- package/dist/operations/work-orders-list-comments.d.ts +34 -0
- package/dist/result.d.ts +5 -1
- package/package.json +1 -1
package/MIGRATION.md
CHANGED
|
@@ -8,7 +8,8 @@ migrar já deve fixar essa versão.
|
|
|
8
8
|
O guia está na ordem em que a migração costuma acontecer: [cliente](#1-criação-do-cliente),
|
|
9
9
|
[métodos](#2-mapa-de-métodos), [resultado](#3-modelo-de-resultado),
|
|
10
10
|
[erros](#4-códigos-de-erro), [escritas](#5-escritas-outcome-vira-effect),
|
|
11
|
-
[comportamento](#6-mudanças-de-comportamento), [exports](#7-exports-removidos-e-renomeados)
|
|
11
|
+
[comportamento](#6-mudanças-de-comportamento), [exports](#7-exports-removidos-e-renomeados),
|
|
12
|
+
[beta.1 para beta.2](#8-da-200-beta1-para-a-200-beta2).
|
|
12
13
|
|
|
13
14
|
## 1. Criação do cliente
|
|
14
15
|
|
|
@@ -69,7 +70,7 @@ Nada do 1.x foi removido sem equivalente: os 23 métodos acima têm destino.
|
|
|
69
70
|
|
|
70
71
|
Operações que **não existiam** no 1.x: `preRegistrations.create`, `preRegistrations.listPlans`,
|
|
71
72
|
`contracts.update`, `contracts.updateStatus`, `contracts.listStatusReasons`, `services.changePlan`,
|
|
72
|
-
`services.addTv`, `services.removeTv`, `crm.contracts.createByCpfCnpj`, `crm.contracts.list` e
|
|
73
|
+
`services.addTv`, `services.removeTv`, `services.addGeneric`, `services.removeGeneric`, `crm.contracts.createByCpfCnpj`, `crm.contracts.list` e
|
|
73
74
|
`request()`. Veja o [README](README.md#referência-de-operações).
|
|
74
75
|
|
|
75
76
|
Mudanças de forma na entrada, além da posição dos argumentos:
|
|
@@ -165,7 +166,8 @@ A regra mudou, e é mais conservadora:
|
|
|
165
166
|
- O 1.x só dava `outcome` em `crm.*`, `ura.openTicket` e `suporte.addCustomerDocument`. No 2.0
|
|
166
167
|
**toda escrita** tem `effect`, incluindo as novas, e `request()` (sempre `"unknown"` depois do envio).
|
|
167
168
|
- A recusa de `ura.openTicket` com HTTP 200 e `status: 0` era `VALIDATION`/`unknown`; agora é
|
|
168
|
-
`REJECTED` com `effect: "unknown"
|
|
169
|
+
`REJECTED` com `effect: "unknown"`; só a do agendamento com formato inválido (`msg` "Data e hora de
|
|
170
|
+
agendamento inválida ...") traz `reason: "INVALID_SCHEDULE"` e `effect: "none"`.
|
|
169
171
|
|
|
170
172
|
Os `reason`s conhecidos e o que fazer diante de `"unknown"` estão no README.
|
|
171
173
|
|
|
@@ -183,8 +185,8 @@ A 2.0 preserva toda chave que recebe, em todos os níveis, e tipa o que conhece:
|
|
|
183
185
|
`INVALID_RESPONSE`, nunca um objeto vazio.
|
|
184
186
|
- Campos estruturais (ids e o que a navegação exige) têm validação estrita (`INVALID_RESPONSE`); campos
|
|
185
187
|
secundários com tipo inesperado saem de `data` com um `warning`, e o original fica em `response.body`.
|
|
186
|
-
-
|
|
187
|
-
|
|
188
|
+
- Tipos de alguns campos são normalizados por campo (ver [a seção 8](#8-da-200-beta1-para-a-200-beta2)):
|
|
189
|
+
onde o SGP varia o tipo, `data` traz um só.
|
|
188
190
|
- As listas que o SGP pagina (`customers.list`, `workOrders.list`, `invoices.list`) devolvem uma
|
|
189
191
|
página com a `paginacao` do SGP; `total` nunca é calculado. As sem paginação mantêm o formato do SGP.
|
|
190
192
|
|
|
@@ -271,6 +273,65 @@ dados pessoais. Nunca registre o resultado cru.
|
|
|
271
273
|
`SgpAddress` continua exportado. `SgpResult`, `SgpError`, `SgpErrorCode` e `SchemaWarning` mantêm o
|
|
272
274
|
nome, com o formato novo descrito acima.
|
|
273
275
|
|
|
276
|
+
## 8. Da 2.0.0-beta.1 para a 2.0.0-beta.2
|
|
277
|
+
|
|
278
|
+
A beta.2 **normaliza o tipo de campos que o SGP manda com tipo variável ou em texto**. É uma em geral uma
|
|
279
|
+
mudança de tipo (quebra de compilação onde você usava o tipo antigo; `invoices.list` é a exceção, abaixo); os nomes não mudam, campos desconhecidos
|
|
280
|
+
ficam como vieram, e o corpo original segue em `response.body`. Regras: número (JSON ou texto com `.`
|
|
281
|
+
decimal e sem separador de milhar) vira `number`; `""` e `null` viram `null` (nunca `0`); texto
|
|
282
|
+
formatado (`"1.234,56"`) nunca é adivinhado: o campo sai de `data` com um `warning`.
|
|
283
|
+
|
|
284
|
+
| Operação | Campo | beta.1 | beta.2 |
|
|
285
|
+
| ------------------------------------- | ------------------------------------------- | ---------------------------------------- | ------------------------------- |
|
|
286
|
+
| `coverage.check` | `lat`, `lng`, `distancia`, `id` de cada CTO | `number \| string` (Geogrid manda texto) | `number \| null` |
|
|
287
|
+
| `services.addTv`, `services.removeTv` | `clientecontrato_id` | `string` | `number \| null` |
|
|
288
|
+
| `workOrders.get` | `servico_id`, `contrato_status_id` | `string` | `number \| null` |
|
|
289
|
+
| `workOrders.get` | `os_setor_id` | `number \| string` | `number \| null` |
|
|
290
|
+
| `workOrders.get` | `contrato_status` | `" Suspenso"` (espaço à esquerda) | `"Suspenso"` (aparado) |
|
|
291
|
+
| `preRegistrations.listPlans` | `gateway.gateway_id`, `gateway.id` | `string \| number` (`""` sem gateway) | `number \| null` |
|
|
292
|
+
| `preRegistrations.create` | `precadastro_id`, `new_contrato_id` | `unknown` (chave não tipada) | `number \| null` (opcional) |
|
|
293
|
+
| `preRegistrations.create` | `new_cliente_id` | `unknown` (chave não tipada) | `CustomerId \| null` (opcional) |
|
|
294
|
+
|
|
295
|
+
Em `preRegistrations.create`, os três ids do sucesso passam a ter tipo, mas **continuam opcionais**: o
|
|
296
|
+
SDK não os inventa, e quando o SGP os omite você segue relendo o cliente por `customers.list({ cpfcnpj })`.
|
|
297
|
+
Os registros mais antigos listam só `message` e o decoder da 1.x descartava chaves desconhecidas, então não
|
|
298
|
+
se sabe se o SGP já enviava os ids antes.
|
|
299
|
+
|
|
300
|
+
**`invoices.list` é mudança de comportamento, não de tipo.** `titulos[].valor`, `valorDesconto`,
|
|
301
|
+
`valorCorrigido`, `valorPago` e `valorPagoParcial` já eram `number | null` na beta.1. O que muda: um `""`
|
|
302
|
+
em `valor` (o SGP manda texto vazio quando não há valor) saía de `data` com um `warning`; agora chega como
|
|
303
|
+
`null`, nunca como `0`. Texto formatado (`"1.234,56"`) continua saindo de `data` com `warning`.
|
|
304
|
+
|
|
305
|
+
**`cpfcnpj` das escritas que gravam o documento.** `preRegistrations.create` e `crm.customers.create`
|
|
306
|
+
passam a enviar o documento na máscara canônica e a recusar localmente o que não for CPF (`personType:
|
|
307
|
+
"F"`) ou CNPJ (`"J"`):
|
|
308
|
+
|
|
309
|
+
| Entrada (`F`) | beta.1 enviava | beta.2 envia ou faz |
|
|
310
|
+
| ------------------------- | --------------- | ------------------------------------------ |
|
|
311
|
+
| `"00000000191"` | `"00000000191"` | `"000.000.001-91"` |
|
|
312
|
+
| `"000.000.001-91"` | igual | igual |
|
|
313
|
+
| `"000 000 001/91"` | igual | `"000.000.001-91"` |
|
|
314
|
+
| `"00000000000191"` (CNPJ) | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
|
|
315
|
+
| `""` ou `"abc"` | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
|
|
316
|
+
|
|
317
|
+
| Entrada (`J`) | beta.1 enviava | beta.2 envia ou faz |
|
|
318
|
+
| ----------------------------------------- | -------------- | ------------------------------------------ |
|
|
319
|
+
| `"00000000000191"` | igual | `"00.000.000/0001-91"` |
|
|
320
|
+
| `"12abc34501de35"` | igual | `"12.ABC.345/01DE-35"` (maiúsculas) |
|
|
321
|
+
| `"12.ABC.345/01DE-35"` | igual | igual |
|
|
322
|
+
| `"12ABC34501DEAB"` (letras nas 2 últimas) | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
|
|
323
|
+
| `"00000000191"` (CPF) | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
|
|
324
|
+
|
|
325
|
+
A recusa traz `error.code === "INVALID_INPUT"`, `attempts: 0`, `effect: "none"` e
|
|
326
|
+
`error.issues` igual a `["cpfcnpj: expected a CPF for personType F: ..."]` (ou `CNPJ`/`J`), sem o valor.
|
|
327
|
+
Só o formato é conferido: os dígitos verificadores não. Trate `INVALID_INPUT` com `error.issues` no
|
|
328
|
+
lugar de formatar o documento por conta própria. Os filtros `cpfcnpj` de leitura não mudam. Quem
|
|
329
|
+
guardou clientes com o documento só em dígitos continua com esses cadastros no SGP: o SDK não os
|
|
330
|
+
corrige.
|
|
331
|
+
|
|
332
|
+
Se você comparava `contrato_status` com o texto com espaço, ou fazia `Number(servico_id)`, remova o
|
|
333
|
+
ajuste. Quem lia `valor` e tratava o campo ausente precisa tratar também `null` (valor ausente no SGP).
|
|
334
|
+
|
|
274
335
|
## Roteiro sugerido
|
|
275
336
|
|
|
276
337
|
1. Troque a criação do cliente (`credentials`) e trate `InvalidConfigurationError` na inicialização.
|
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Cliente TypeScript não oficial para a API HTTP do SGP, o ERP de provedores de internet da TSMX.
|
|
4
4
|
Sem vínculo com a TSMX.
|
|
5
5
|
|
|
6
|
-
> **Versão 2.0.** Esta documentação descreve a 2.0
|
|
7
|
-
> 1.x
|
|
8
|
-
> [MIGRATION.md](MIGRATION.md).
|
|
6
|
+
> **Versão 2.0 (beta).** Esta documentação descreve a 2.0, publicada em beta na tag `next` do npm
|
|
7
|
+
> (`npm install sgp-sdk@next`); a `latest` continua na 1.x até a 2.0.0 estável. A série 1.x está
|
|
8
|
+
> congelada: não recebe mais mudanças. Para migrar, leia [MIGRATION.md](MIGRATION.md).
|
|
9
9
|
|
|
10
10
|
## O que é e o que não é
|
|
11
11
|
|
|
@@ -144,9 +144,15 @@ status. Os existentes:
|
|
|
144
144
|
| ----------------------------- | ------------------------------------------ | -------------------------------------- |
|
|
145
145
|
| `TOKEN_ROUTE_NOT_ALLOWED` | qualquer (com `FORBIDDEN`) | 403 "credenciais não foram fornecidas" |
|
|
146
146
|
| `DOCUMENT_ALREADY_REGISTERED` | `preRegistrations.create` | 402, CPF já cadastrado |
|
|
147
|
+
| `DOCUMENT_ALREADY_REGISTERED` | `crm.customers.create` | 400 `errors.cpfcnpj`, CPF já no CRM |
|
|
148
|
+
| `DOCUMENT_INVALID` | `crm.customers.create` | 400 `errors.cpfcnpj` "CPF inválido." |
|
|
149
|
+
| `DOCUMENT_INVALID` | `preRegistrations.create` | 400 `message` "CPF inválido" |
|
|
150
|
+
| `LOGIN_ALREADY_REGISTERED` | `preRegistrations.create` | 400 `message` "Login ... já existe" |
|
|
151
|
+
| `INVALID_SCHEDULE` | `occurrences.create` | 200 `status: 0`, agendamento inválido |
|
|
147
152
|
| `STATUS_NOT_CHANGED` | `contracts.updateStatus` | 400 "Status de Contrato não alterado." |
|
|
148
153
|
| `CUSTOMER_NOT_IN_CRM` | `crm.contracts.create`, `.createByCpfCnpj` | 400 "Não encontrado cliente CRM ..." |
|
|
149
154
|
| `CONTRACT_NOT_ACTIVE` | `services.addTv` | 400, contrato não ativo |
|
|
155
|
+
| `PLAN_NOT_GENERIC` | `services.addGeneric` | 400, plano não é do tipo genérico |
|
|
150
156
|
|
|
151
157
|
Sem `reason`, a falha continua útil: `code`, `effect`, `sgp` e `response.body` dizem tudo o que o
|
|
152
158
|
SGP disse.
|
|
@@ -162,7 +168,8 @@ Só escritas têm `error.effect`; leituras não têm. O código sozinho não det
|
|
|
162
168
|
`error` ou `detail` como texto). Corrigir a entrada e chamar de novo é seguro.
|
|
163
169
|
- **`"unknown"`**: o SGP pode ter aplicado. Vale para timeout, falha de rede, cancelamento depois do
|
|
164
170
|
envio, 5xx, 3xx, 2xx fora do contrato, 4xx com corpo ilegível ou de formato não reconhecido, a
|
|
165
|
-
recusa com HTTP 200 de `occurrences.create` (`status: 0
|
|
171
|
+
recusa com HTTP 200 de `occurrences.create` (`status: 0`, salvo a do formato do agendamento, de
|
|
172
|
+
`reason` `INVALID_SCHEDULE`, que é `"none"`) e o "invólucro genérico" do SGP
|
|
166
173
|
(`errors` como **array**, "Ocorreu um erro: ..."), salvo quando a operação o declara como
|
|
167
174
|
recusa conhecida.
|
|
168
175
|
|
|
@@ -171,16 +178,17 @@ Uma observação de "nada foi aplicado" é registrada como observação com seu
|
|
|
171
178
|
|
|
172
179
|
**Diante de `"unknown"`, não reenvie às cegas.** Releia o estado e só então decida:
|
|
173
180
|
|
|
174
|
-
| Escrita que ficou em `unknown`
|
|
175
|
-
|
|
|
176
|
-
| `crm.customers.create`
|
|
177
|
-
| `crm.contracts.create`, `crm.contracts.createByCpfCnpj`
|
|
178
|
-
| `crm.customers.updateStatus`
|
|
179
|
-
| `contracts.updateStatus`, `contracts.update`
|
|
180
|
-
| `preRegistrations.create`
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
181
|
+
| Escrita que ficou em `unknown` | Leitura que verifica |
|
|
182
|
+
| ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
183
|
+
| `crm.customers.create` | `customers.search` ou `customers.list` pelo documento |
|
|
184
|
+
| `crm.contracts.create`, `crm.contracts.createByCpfCnpj` | `crm.contracts.list` (por documento) |
|
|
185
|
+
| `crm.customers.updateStatus` | ler o cliente antes de reenviar |
|
|
186
|
+
| `contracts.updateStatus`, `contracts.update` | `contracts.list({ contrato })` |
|
|
187
|
+
| `preRegistrations.create` | `customers.list({ cpfcnpj })` (só quando a resposta de sucesso não traz `new_cliente_id`) |
|
|
188
|
+
| `contracts.checkConnection` | `occurrences.list({ contrato })` (uma ocorrência pode ter sido aberta em manutenção) |
|
|
189
|
+
| `occurrences.create` | `occurrences.list({ contrato })` (traz a OS em `ordens_servicos[]`) ou `workOrders.list({ contrato })`; com `desativa_os: 1` não há OS para consultar |
|
|
190
|
+
| `services.changePlan`, `services.addTv`, `services.removeTv`, `services.addGeneric`, `services.removeGeneric` | `customers.list` (serviços do contrato) |
|
|
191
|
+
| `documents.add` | `documents.list` |
|
|
184
192
|
|
|
185
193
|
### `sgp`, `response`, `warnings`, `attempts`
|
|
186
194
|
|
|
@@ -200,7 +208,7 @@ Uma observação de "nada foi aplicado" é registrada como observação com seu
|
|
|
200
208
|
- **Fidelidade.** Campos conhecidos são tipados; os desconhecidos chegam em `data` em todos os níveis
|
|
201
209
|
(raiz, aninhados, arrays), sem serem descartados. Um item que o SDK não consegue interpretar faz a
|
|
202
210
|
resposta falhar com `INVALID_RESPONSE`; nunca vira `{}` nem `[]`.
|
|
203
|
-
- **Paginação.** `customers.list`, `workOrders.list` e `invoices.list` devolvem **uma página**, com
|
|
211
|
+
- **Paginação.** `customers.list`, `workOrders.list`, `occurrences.list` e `invoices.list` devolvem **uma página**, com
|
|
204
212
|
a `paginacao` do SGP como veio (`total` nunca é calculado pelo SDK). Para a próxima página, passe
|
|
205
213
|
`offset`. Listas sem paginação mantêm o formato do SGP (array ou objeto), sem envelope.
|
|
206
214
|
- **Credenciais nos headers.** Os headers capturados nunca carregam o token nem o app: o valor de
|
|
@@ -338,11 +346,11 @@ Veja `examples/request-raw.ts` no repositório.
|
|
|
338
346
|
|
|
339
347
|
Alguns ids têm tipo "com marca" (apenas em tempo de compilação; em runtime são números):
|
|
340
348
|
|
|
341
|
-
| Tipo | De onde vem | Para onde vai
|
|
342
|
-
| ----------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
343
|
-
| `CustomerId` | `customers.list` (`clientes[].id`), `customers.search` (`clienteId`), `crm.customers.create` (`cliente_id`) | `cliente_id` de `crm.*`, `documents.*`, `customers.list`, `invoices.list`
|
|
344
|
-
| `PlanId` | `plans.list` (`planos[].id`) | `plano` de `contracts.list`, `plano_id` de `services.changePlan` e de `crm.contracts.create`, `planobase_id` de `services.addTv` |
|
|
345
|
-
| `PreRegistrationPlanId` | `preRegistrations.listPlans` (`id`) | `plano_id` de `preRegistrations.create`
|
|
349
|
+
| Tipo | De onde vem | Para onde vai |
|
|
350
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
351
|
+
| `CustomerId` | `customers.list` (`clientes[].id`), `customers.search` (`clienteId`), `crm.customers.create` (`cliente_id`) | `cliente_id` de `crm.*`, `documents.*`, `customers.list`, `invoices.list` |
|
|
352
|
+
| `PlanId` | `plans.list` (`planos[].id`) | `plano` de `contracts.list`, `plano_id` de `services.changePlan` e de `crm.contracts.create`, `planobase_id` de `services.addTv` e de `services.addGeneric` |
|
|
353
|
+
| `PreRegistrationPlanId` | `preRegistrations.listPlans` (`id`) | `plano_id` de `preRegistrations.create` |
|
|
346
354
|
|
|
347
355
|
Um cliente CRM tem o mesmo `CustomerId` do cliente. **O id de um contrato não é um `CustomerId`**, e
|
|
348
356
|
o compilador recusa um no lugar do outro e um número solto onde um id é esperado. Para marcar um
|
|
@@ -358,13 +366,14 @@ conversão entre catálogos não é feita pelo SDK.
|
|
|
358
366
|
Códigos fixos do SGP exportados como constantes; as operações aceitam qualquer número e o SGP
|
|
359
367
|
decide.
|
|
360
368
|
|
|
361
|
-
| Constante
|
|
362
|
-
|
|
|
363
|
-
| `CONTRACT_STATUS`
|
|
364
|
-
| `BILLING_METHOD`
|
|
365
|
-
| `ACQUISITION_MODE`
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
369
|
+
| Constante | Valores | Evidência |
|
|
370
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
371
|
+
| `CONTRACT_STATUS` | `active` 1, `inactive` 2, `canceled` 3, `suspended` 4, `technicalInfeasibility` 5, `new` 6, `activeReducedSpeed` 7 | 1 e 4 confirmados (200 e releitura); 2 enviado e recusado a partir de Ativo; 3, 5 e 7 do painel; 6 documentado pelo fornecedor, nunca observado |
|
|
372
|
+
| `BILLING_METHOD` | `boleto` 1, `automaticDebit` 2, `booklet` 3, `recurringCharge` 4, `pix` 6 | códigos globais fixos; o 5 não é listado (documentado para uma rota, nunca confirmado) |
|
|
373
|
+
| `ACQUISITION_MODE` | `owned` 0, `loan` 1 | o valor 2, que a documentação do fornecedor lista para o CRM, foi recusado ao vivo |
|
|
374
|
+
| `CONNECTION_STATUS` | `notChecked` 0, `online` 1, `offline` 2, `maintenance` 9 | 1 e 2 observados; 0 e 9 só na documentação do fornecedor |
|
|
375
|
+
| `SERVICE_TYPE` | `internet` 1 | só o 1 foi enviado ao SGP |
|
|
376
|
+
| `CRM_STATUS` | `underAnalysis` 1 ... `technicalFeasibilityAnalysis` 10 | só o 6 (`contractMadeInSgp`) foi enviado ao vivo |
|
|
368
377
|
|
|
369
378
|
O SDK não guarda tabela de transições de status: quem decide o que é permitido é o SGP.
|
|
370
379
|
|
|
@@ -381,74 +390,107 @@ Legenda. **Natureza:** _leitura_ é repetível com `maxRetries`; _escrita_ nunca
|
|
|
381
390
|
`form-files` (multipart com arquivo). **Evidência**, resumida (detalhes por cenário em
|
|
382
391
|
[COMPATIBILITY.md](COMPATIBILITY.md)): _observado_ (resposta real capturada), _parcial_ (sucesso
|
|
383
392
|
observado, mas recusas só documentadas ou reconstruídas, ou o inverso), _documentado_ (só a
|
|
384
|
-
documentação do fornecedor), _reconstruído_ (corpo reconstruído a partir de relatos ou testes, sem
|
|
393
|
+
documentação do fornecedor), _confirmado pelo fornecedor, não testado_ (o suporte afirmou, nunca exercitado), _reconstruído_ (corpo reconstruído a partir de relatos ou testes, sem
|
|
385
394
|
captura bruta).
|
|
386
395
|
|
|
387
396
|
### `customers`
|
|
388
397
|
|
|
389
398
|
| Método | Rota e codificação | Natureza | Notas | Evidência |
|
|
390
399
|
| ------------------------- | --------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
391
|
-
| `customers.list(input?)` | `POST /api/ura/clientes/` · json | leitura | Uma página; `paginacao` do SGP como veio; filtros `cliente_id`, `cpfcnpj`, `cliente_nome
|
|
400
|
+
| `customers.list(input?)` | `POST /api/ura/clientes/` · json | leitura | Uma página; `paginacao` do SGP como veio; filtros `cliente_id`, `cpfcnpj`, `cliente_nome` e `login` (login PPPoE exato; segredo); contratos e serviços aninhados chegam inteiros | observado |
|
|
392
401
|
| `customers.search(input)` | `POST /api/ura/consultacliente/` · json | leitura | Devolve **candidatos** e nunca escolhe um; ao menos um critério (`cpfcnpj`, `contrato`, `nome`, `login`, `telefone`); texto vazio é recusado; sem resultado é sucesso com `contratos: []`; cada candidato traz credenciais do serviço | observado (corpo mascarado, 1.x) |
|
|
393
402
|
|
|
394
403
|
### `crm.customers` e `crm.contracts`
|
|
395
404
|
|
|
396
|
-
| Método | Rota e codificação | Natureza | Notas
|
|
397
|
-
| -------------------------------------- | ------------------------------------------------------ | -------- |
|
|
398
|
-
| `crm.customers.create(input)` | `POST /api/crm/cliente/{F\|J}` · json | escrita | `personType` escolhe a rota; `endereco` aninhado, como o SGP o lê.
|
|
399
|
-
| `crm.customers.updateStatus(input)` | `POST /api/crm/cliente/{cliente_id}/status/` · json | escrita | Códigos em `CRM_STATUS`. Cliente que já saiu do CRM (ou status 6 repetido): 404 `{error:"Cadastro não encontrado"}`, `NOT_FOUND`, `effect: "none"`
|
|
400
|
-
| `crm.contracts.create(input)` | `POST /api/crm/cliente/{cliente_id}/contratos/` · json | escrita | Só para cliente ainda no funil CRM. Recusa `CUSTOMER_NOT_IN_CRM`, `effect: "none"`. `plano_id` é `PlanId`; `modoaquisicao` é `ACQUISITION_MODE`
|
|
401
|
-
| `crm.contracts.createByCpfCnpj(input)` | `POST /api/crm/cliente/contratos/?cpfcnpj=` · json | escrita | Documento na **query** do POST. Mesma recusa `CUSTOMER_NOT_IN_CRM`. Com documento duplicado, qual cliente recebe o contrato não foi verificado. **Nenhum sucesso foi observado nesta rota**
|
|
402
|
-
| `crm.contracts.list(input)` | `GET /api/crm/cliente/contratos/?cpfcnpj=` · query | leitura | Documento que não é cliente CRM: 400, `REJECTED`, sem `reason`
|
|
405
|
+
| Método | Rota e codificação | Natureza | Notas | Evidência |
|
|
406
|
+
| -------------------------------------- | ------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
407
|
+
| `crm.customers.create(input)` | `POST /api/crm/cliente/{F\|J}` · json | escrita | `personType` escolhe a rota; `endereco` aninhado, como o SGP o lê. O SDK envia `cpfcnpj` na máscara canônica (CPF `999.999.999-99` em `F`, CNPJ `AA.AAA.AAA/AAAA-99` em `J`, alfanumérico em maiúsculas, com ou sem pontuação na entrada) e recusa localmente (`INVALID_INPUT`, `error.issues` `["cpfcnpj: ..."]`, nada enviado) outro formato ou o tipo errado para a rota; o SDK confere só o formato, mas o SGP confere os dígitos verificadores do CPF (400 `DOCUMENT_INVALID`, `effect: "none"`; os do CNPJ nunca foram testados). O SGP recusa documento já cadastrado, em qualquer status (400 `DOCUMENT_ALREADY_REGISTERED`); **exceção observada: um cliente cujo documento foi gravado sem formatação (ex.: um pré-cadastro só com dígitos, antes do SDK formatar) não foi detectado e cria OUTRO cliente com o mesmo documento**: confira antes (`customers.list({ cpfcnpj })`). 400 de validação de campo: `REJECTED`, `effect: "none"` | observado (`/F`); `/J` confirmado pelo fornecedor, não testado |
|
|
408
|
+
| `crm.customers.updateStatus(input)` | `POST /api/crm/cliente/{cliente_id}/status/` · json | escrita | Códigos em `CRM_STATUS`. Cliente que já saiu do CRM (ou status 6 repetido): 404 `{error:"Cadastro não encontrado"}`, `NOT_FOUND`, `effect: "none"` | observado (status 6; o 404 vem de captura da 1.x) |
|
|
409
|
+
| `crm.contracts.create(input)` | `POST /api/crm/cliente/{cliente_id}/contratos/` · json | escrita | Só para cliente ainda no funil CRM. Recusa `CUSTOMER_NOT_IN_CRM`, `effect: "none"`. `plano_id` é `PlanId`; `modoaquisicao` é `ACQUISITION_MODE` | parcial |
|
|
410
|
+
| `crm.contracts.createByCpfCnpj(input)` | `POST /api/crm/cliente/contratos/?cpfcnpj=` · json | escrita | Documento na **query** do POST. Mesma recusa `CUSTOMER_NOT_IN_CRM`. Com documento duplicado, qual cliente recebe o contrato não foi verificado. **Nenhum sucesso foi observado nesta rota** | parcial (sucesso só documentado) |
|
|
411
|
+
| `crm.contracts.list(input)` | `GET /api/crm/cliente/contratos/?cpfcnpj=` · query | leitura | Documento que não é cliente CRM: 400, `REJECTED`, sem `reason` | observado |
|
|
403
412
|
|
|
404
413
|
### `preRegistrations`
|
|
405
414
|
|
|
406
|
-
| Método | Rota e codificação | Natureza | Notas
|
|
407
|
-
| -------------------------------- | ----------------------------------------------------------- | -------- |
|
|
408
|
-
| `preRegistrations.create(input)` | `POST /api/precadastro/{F\|J}` · form | escrita | Endereço em campos soltos no topo da entrada (`logradouro`, `numero`, ...), com os nomes do SGP. Com `precadastro_ativar: 1` vira cliente definitivo; contrato só se plano e cobrança forem suficientes. Sucesso traz só `message`,
|
|
409
|
-
| `preRegistrations.listPlans()` | `POST /api/precadastro/plano/list` · form (sem barra final) | leitura | `PreRegistrationPlanId`: catálogo próprio, não é o de `plans.list`
|
|
410
|
-
| `preRegistrations.listDueDays()` | `POST /api/precadastro/vencimento/list` · json | leitura | `id` é o `vencimento_id` de `create`; `dia` é o dia do mês
|
|
411
|
-
| `preRegistrations.listSellers()` | `POST /api/precadastro/vendedor/list` · json | leitura | `id` é o `vendedor_id`; nome, CPF e e-mail são dados pessoais
|
|
415
|
+
| Método | Rota e codificação | Natureza | Notas | Evidência |
|
|
416
|
+
| -------------------------------- | ----------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
417
|
+
| `preRegistrations.create(input)` | `POST /api/precadastro/{F\|J}` · form | escrita | Endereço em campos soltos no topo da entrada (`logradouro`, `numero`, ...), com os nomes do SGP. O SDK envia `cpfcnpj` na máscara canônica (CPF em `F`, CNPJ em `J`; o SGP grava o que recebe e um CPF só com dígitos escapou da checagem de duplicidade do CRM) e recusa localmente outro formato ou o tipo errado para a rota (`INVALID_INPUT`, `error.issues` `["cpfcnpj: ..."]`); o SGP confere os dígitos verificadores do CPF e recusa o errado (400 `{ message: "CPF inválido", error: "Requisição inválida." }`, `REJECTED`, `DOCUMENT_INVALID`, `effect: "none"`; os do CNPJ nunca foram testados). O SGP recusa um `login` PPPoE já em uso (400 `{ message: "Login <login> já existe", error: "Requisição inválida." }`, `REJECTED`, `LOGIN_ALREADY_REGISTERED`, `effect: "none"`, observado uma vez; `error.sgp` traz só o `error`, e o login que o `message` repete fica em `response.body`, nunca em outro campo do erro): confira antes com `customers.list({ login })`. Com `precadastro_ativar: 1` vira cliente definitivo; contrato só se plano e cobrança forem suficientes. Sucesso traz `message` e, quando o SGP os manda (a captura mais recente mandou; os registros antigos listam só `message`, e como o decoder da 1.x descartava chaves desconhecidas não se sabe se os ids já vinham), `new_cliente_id` (`CustomerId`), `new_contrato_id` e `precadastro_id`, opcionais: sem eles o SDK não inventa nada, releia por `customers.list({ cpfcnpj })`. CPF existente: 402, `REJECTED`, `DOCUMENT_ALREADY_REGISTERED`, `effect: "none"` | parcial (recusa observada; sucesso: `{message}` do fornecedor e, na captura bruta mais recente, também os ids; `/J` confirmado pelo fornecedor, não testado) |
|
|
418
|
+
| `preRegistrations.listPlans()` | `POST /api/precadastro/plano/list` · form (sem barra final) | leitura | `PreRegistrationPlanId`: catálogo próprio, não é o de `plans.list` | observado |
|
|
419
|
+
| `preRegistrations.listDueDays()` | `POST /api/precadastro/vencimento/list` · json | leitura | `id` é o `vencimento_id` de `create`; `dia` é o dia do mês | observado (corpo mascarado, 1.x) |
|
|
420
|
+
| `preRegistrations.listSellers()` | `POST /api/precadastro/vendedor/list` · json | leitura | `id` é o `vendedor_id`; nome, CPF e e-mail são dados pessoais | observado (corpo mascarado, 1.x) |
|
|
412
421
|
|
|
413
422
|
### `contracts` e `services`
|
|
414
423
|
|
|
415
|
-
| Método
|
|
416
|
-
|
|
|
417
|
-
| `contracts.
|
|
418
|
-
| `contracts.
|
|
419
|
-
| `contracts.
|
|
420
|
-
| `contracts.
|
|
421
|
-
| `
|
|
422
|
-
| `
|
|
423
|
-
| `services.
|
|
424
|
+
| Método | Rota e codificação | Natureza | Notas | Evidência |
|
|
425
|
+
| ---------------------------------- | ----------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
426
|
+
| `contracts.listServices(input?)` | `POST /api/suporte/contrato/list/` · form (com barra final) | leitura | Suporte técnico: um array com UMA LINHA POR SERVIÇO (internet e TV) do contrato, com cliente, contrato, endereço e plano repetidos; `servico_online` diz se o serviço está online e a linha online traz a sessão RADIUS (`rad_*`: IP, MAC, NAS, tempo de conexão, contadores). **Exige ao menos um filtro** (`contrato_id` ou `cliente_id`): sem filtro o SGP lista os serviços de todos os clientes, com **senhas de serviço em texto claro**, então o SDK recusa a chamada sem filtro (`INVALID_INPUT`, `attempts: 0`, nada enviado). Ids que o SGP manda como texto e os contadores RADIUS são números, `contrato_status` vem aparado. Login, senha, MACs, IPs (inclusive prefixos IPv6 e NAS) e ids de sessão são segredos; nome, e-mail, contato e endereço são pessoais (`getSensitivity("contracts.listServices")`) | observado (bruta, contrato sintético offline; a linha online é reconstruída da forma mascarada de um contrato real, só tipos) |
|
|
427
|
+
| `contracts.checkConnection(input)` | `POST /api/ura/verificaacesso/` · form (com barra final) | **escrita** | Veredito do SGP sobre a conexão (`status` 1 online, 2 offline, 9 manutenção, 0 nada checado: `CONNECTION_STATUS`). `contrato` (exercitado) ou `telefone` (documentado); `status_all: 1` inclui contratos que o filtro padrão deixa de fora (um contrato suspenso devolveu `[]` sem ele). **É DECLARADA ESCRITA**: o fornecedor documenta que, em manutenção ativa, o SGP abre uma ocorrência por padrão, mesmo sem `protocolo_ura` (não testado). Nunca é repetida, e uma falha traz `effect` (em geral `"unknown"`: releia `occurrences.list({ contrato })` antes de reenviar). Chame `maintenance.list()` antes. `protocolo_ura` não é oferecido (use `occurrences.create`). `data` é SEMPRE um array (um item por serviço de internet): o objeto único que o SGP devolve num contrato ativo sem `status_all` é embrulhado; `[]` não é "offline", é sem veredito. `login` é segredo; `razaoSocial` e `cpfCnpj` são pessoais | observado (bruta, contrato sintético suspenso; o objeto único é reconstruído da forma mascarada de um contrato real) |
|
|
428
|
+
| `contracts.list(input?)` | `POST /api/ura/listacontrato/` · json | leitura | Sem paginação; array simples; sem filtro pode vir a base inteira do provedor; `plano` é `PlanId` | observado (corpo mascarado, 1.x) |
|
|
429
|
+
| `contracts.updateStatus(input)` | `POST /api/ura/contrato/status/edit/` · json | escrita | Ativar inicia a cobrança. O SGP decide as transições. Recusa `STATUS_NOT_CHANGED` (`effect: "none"`). `motivo` vem de `contracts.listStatusReasons` | parcial (200 observado; a recusa é reconstruída) |
|
|
430
|
+
| `contracts.update(input)` | `POST /api/ura/contrato/edit/` · json | escrita | Só `forma_cobranca` (`BILLING_METHOD`); devolve `resposta.alterados` como o SGP mandou. Sem recusa conhecida | observado |
|
|
431
|
+
| `contracts.listStatusReasons()` | `POST /api/ura/contrato/status/motivos/` · json | leitura | Cada provedor tem a sua lista: leia antes de passar `motivo` | observado |
|
|
432
|
+
| `services.changePlan(input)` | `POST /api/suporte/service/update/{servico_id}/` · form | escrita | `action` fixa `change_plano`; `servico_tipo` obrigatório (só `1` exercitado); evento de cobrança. Sucesso traz só `msg` | observado |
|
|
433
|
+
| `services.addTv(input)` | `POST /api/servico/tv` · form | escrita | HTTP 201 com `servico_id`; só contratos ativos: recusa `CONTRACT_NOT_ACTIVE` (`effect: "none"`); `planobase_id` é `PlanId` | parcial (201 observado; a recusa é reconstruída) |
|
|
434
|
+
| `services.removeTv(input)` | `DELETE /api/servico/tv/{servico_id}` · form | escrita | O contrato vai num corpo multipart no DELETE, como o SGP espera. Sem recusa conhecida | observado |
|
|
435
|
+
| `services.addGeneric(input)` | `POST /api/servico/generico` · form | escrita | Rota que a TSMX recomenda para serviço extra do tipo genérico. `planobase_id` é `PlanId` de um plano criado como genérico no painel. Plano de outro tipo: recusa `PLAN_NOT_GENERIC` (`effect: "none"`). Sucesso nunca observado (o provedor não tem plano genérico): `data` é o objeto JSON do SGP, sem campo assumido | parcial (a recusa foi vista ao vivo, corpo reconstruído; sucesso documentado) |
|
|
436
|
+
| `services.removeGeneric(input)` | `DELETE /api/servico/generico/{servico_id}` · form | escrita | O contrato vai num corpo multipart, como em `removeTv`. O fornecedor documenta que a rota não remove o único serviço do contrato; nenhum corpo dessa recusa foi capturado, então não há `reason`. Sucesso nunca observado: `data` é o objeto JSON do SGP | documentado, nunca observado |
|
|
424
437
|
|
|
425
438
|
### `plans`, `invoices`, `workOrders`, `occurrences`
|
|
426
439
|
|
|
427
|
-
| Método
|
|
428
|
-
|
|
|
429
|
-
| `plans.list()`
|
|
430
|
-
| `invoices.list(input?)`
|
|
431
|
-
| `workOrders.list(input?)`
|
|
432
|
-
| `workOrders.
|
|
433
|
-
| `
|
|
434
|
-
| `
|
|
435
|
-
| `occurrences.
|
|
440
|
+
| Método | Rota e codificação | Natureza | Notas | Evidência |
|
|
441
|
+
| -------------------------------- | ---------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
442
|
+
| `plans.list()` | `GET /api/ura/consultaplano/` · query | leitura | Mantém o formato do SGP (`planos` e totais); `planos[].id` é `PlanId` | observado |
|
|
443
|
+
| `invoices.list(input?)` | `POST /api/ura/titulos/` · json | leitura | Uma página; `paginacao.total` ausente é `INVALID_RESPONSE`; máximo de 250 por página é do fornecedor. Valores (`valor`, `valorDesconto`, `valorCorrigido`, `valorPago`, `valorPagoParcial`) são `number` em reais ou `null` (o SGP manda `""` quando não há valor); texto formatado como `"1.234,56"` não é adivinhado e sai de `data` com `warning`. Traz nome, documento, links de pagamento e PIX | parcial (página vazia observada; página populada reconstruída) |
|
|
444
|
+
| `workOrders.list(input?)` | `POST /api/ura/ordemservico/list/` · json | leitura | Uma página; `ocorrencia` é texto e continua texto | observado |
|
|
445
|
+
| `workOrders.get(input)` | `POST /api/os/list/id/{id}` · form (sem barra final) | leitura | Um objeto plano com 72 campos (OS, cliente, contrato, endereço, plano e serviço); a coleção do fornecedor mostra um array de um elemento e o SGP mandou o objeto. **Traz senhas em texto claro** (`servico_password`, `wan_password`, `wifi_password`, `wifi_password_5`) e login, MAC e IP do serviço: segredos; nome, e-mail, contatos, endereço e texto livre são pessoais. Normalizado por campo: `servico_id`, `contrato_status_id` e `os_setor_id` são números (o SGP manda texto) e `contrato_status` vem aparado; o resto como veio | observado (bruta, ao vivo; as senhas de Wi-Fi e WAN vieram vazias) |
|
|
446
|
+
| `workOrders.listComments(input)` | `GET /api/os/{id}/comentario/list/` · query | leitura | Array do SGP sem envelope; vazio = sem comentários. Texto do comentário e autor são pessoais | parcial (bruta: só `[]`; o formato dos itens é só documentado) |
|
|
447
|
+
| `workOrders.listReasons()` | `GET /api/os/ocorrencia/motivo/list/` · query | leitura | `id` e `codigo` são distintos; `occurrences.create` usa o `codigo` em `motivoos` | observado (corpo mascarado, 1.x) |
|
|
448
|
+
| `occurrences.create(input)` | `POST /api/ura/chamado/` · json | escrita | "Chamado" do SGP. Devolve `id` da **ocorrência** e `protocolo`, nunca o id da OS (leia com `occurrences.list`). `data_hora_agendamento` tem de ser exatamente `AAAA-MM-DD HH:MM`: o SGP recusa segundos (HTTP 200, `status: 0`, `msg` "Data e hora de agendamento inválida, formato esperado: AAAA-MM-DD HH:MM"; `REJECTED`, `INVALID_SCHEDULE`, `effect: "none"`, observado uma vez, com releitura: nada foi criado) e o SDK não confere o formato antes (quem decide é o SGP). Qualquer outra recusa com HTTP 200 e `status: 0`: `REJECTED`, `effect: "unknown"`. Observado: ocorrência sem `motivoos` é aceita e o SGP cria a OS mesmo assim; `status_encerrado: 1` encerra ocorrência e OS; encerrar uma OS de instalação (`motivoos` 10) não altera o status do contrato | parcial (sucesso: corpo mascarado, 1.x; recusa do agendamento: bruta; outras recusas: reconstruídas) |
|
|
449
|
+
| `occurrences.list(input?)` | `POST /api/ura/ocorrencia/list/` · form | leitura | **Exige ao menos um filtro (de preferência `contrato`): sem filtro o SGP lista as ocorrências de todos os clientes (até 1000), com nomes e texto livre, então o SDK recusa a chamada sem filtro (`INVALID_INPUT`, `attempts: 0`, nada enviado); `offset` e `limit` sozinhos não contam.** Uma página; devolve a OS de cada ocorrência em `ordens_servicos[]` (é o caminho do chamado até a OS: `ordens_servicos[].id`). Só `contrato` e `limit` foram enviados; os demais filtros são os da coleção do fornecedor | observado (bruta, ao vivo: contrato com e sem ocorrência) |
|
|
450
|
+
| `occurrences.listTypes()` | `GET /api/os/ocorrencia/tipo/list/` · query | leitura | `id` e `codigo`; `occurrences.create` usa o `codigo` em `ocorrenciatipo` | observado (corpo mascarado, 1.x) |
|
|
451
|
+
| `occurrences.listMethods()` | `GET /api/ura/ocorrencia/metodo/list/` · query | leitura | | observado (corpo mascarado, 1.x) |
|
|
436
452
|
|
|
437
453
|
### `documents`, `coverage`, `catalogs`, `experimental`
|
|
438
454
|
|
|
439
|
-
| Método | Rota e codificação | Natureza | Notas
|
|
440
|
-
| -------------------------------------- | ------------------------------------------------------------------- | -------- |
|
|
441
|
-
| `documents.add(input)` | `PUT /api/suporte/cliente/{cliente_id}/documento/add/` · form-files | escrita | Sucesso é 2xx com corpo **vazio** (`data: null`, nada identifica o documento); qualquer outro corpo 2xx é `INVALID_RESPONSE` com `effect: "unknown"`
|
|
442
|
-
| `documents.list(input)` | `GET /api/suporte/cliente/{cliente_id}/documento/list/` · query | leitura | `cliente_id` é um `CustomerId` positivo; array vazio = sem documentos
|
|
443
|
-
| `coverage.check(input)` | `GET /api/ura/viabilidadeinstalacao` · query (sem barra final) | leitura | `gateway`, `raio` (metros) e `coordenada` (`"lat,lng"`) obrigatórios; o SDK não geocodifica;
|
|
444
|
-
| `
|
|
445
|
-
| `
|
|
446
|
-
| `
|
|
447
|
-
| `
|
|
455
|
+
| Método | Rota e codificação | Natureza | Notas | Evidência |
|
|
456
|
+
| -------------------------------------- | ------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
457
|
+
| `documents.add(input)` | `PUT /api/suporte/cliente/{cliente_id}/documento/add/` · form-files | escrita | Sucesso é 2xx com corpo **vazio** (`data: null`, nada identifica o documento); qualquer outro corpo 2xx é `INVALID_RESPONSE` com `effect: "unknown"` | reconstruído |
|
|
458
|
+
| `documents.list(input)` | `GET /api/suporte/cliente/{cliente_id}/documento/list/` · query | leitura | `cliente_id` é um `CustomerId` positivo; array vazio = sem documentos | observado (corpo mascarado, 1.x) |
|
|
459
|
+
| `coverage.check(input)` | `GET /api/ura/viabilidadeinstalacao` · query (sem barra final) | leitura | `gateway`, `raio` (metros) e `coordenada` (`"lat,lng"`) obrigatórios; o SDK não geocodifica; `lat`, `lng`, `distancia` e `id` de cada CTO são números (o Geogrid manda texto, convertido) | observado (corpo mascarado, 1.x; SGPMaps e Geogrid) |
|
|
460
|
+
| `coverage.checkAddress(input)` | `POST /api/ura/viabilidade/` · form | leitura | Viabilidade por **endereço**, sem coordenada: `cep`, `cidade`, `logradouro`, `bairro`, `numero_inicial`, `numero_final`; ao menos um (o fornecedor manda usar um dos filtros). Devolve o objeto do SGP como veio: `{ viabilidade: true }` ou `{}`. **Sem a chave `viabilidade` = desconhecido, nunca "sem cobertura"**; a resposta de "sem cobertura" nunca foi observada. O endereço é dado pessoal | observado (bruta, ao vivo: `cep` sozinho e `cidade` sozinha; os demais filtros só documentados) |
|
|
461
|
+
| `coverage.listGateways()` | `GET /api/ura/listgatewaymapa` · query (sem barra final) | leitura | Gateways de mapa do provedor; o `id` de cada um é o `gateway` de `coverage.check`; array vazio = nenhum gateway | observado (corpo, ao vivo; Geogrid e SGPMaps) |
|
|
462
|
+
| `maintenance.list()` | `GET /api/ura/manutencao/list/` · query | leitura | Avisos de manutenção (SGP "manutenção"), **inclusive os inativos**, sem filtro nem paginação: filtre por `ativa` e pelo período (`data_inicial`, `data_final`). Array do SGP, sem envelope; as listas de elementos afetados vieram vazias, então o conteúdo delas é desconhecido | observado (bruta, ao vivo: três avisos, todos inativos) |
|
|
463
|
+
| `catalogs.listPops()` | `POST /api/ura/pops/` · json | leitura | | observado (corpo mascarado, 1.x) |
|
|
464
|
+
| `catalogs.listNas()` | `POST /api/ura/nas/list/` · json | leitura | `endereco_ip` é segredo | observado (corpo mascarado, 1.x) |
|
|
465
|
+
| `catalogs.listBillingProfiles()` | `GET /api/ura/portador/` · query | leitura | "Portadores" do SGP; os ids alimentam o filtro `portador` de `invoices.list` | observado (corpo mascarado, 1.x) |
|
|
466
|
+
| `experimental.annotations.list(input)` | `GET /api/ura/cliente/anotacao/list/` · query | leitura | **Experimental.** Seleção local, corpo retido. Veja [leituras com escopo](#leituras-com-escopo) | reconstruído (corpo sintético; tipos de campo observados) |
|
|
448
467
|
|
|
449
468
|
Todas as leituras acima aceitam `maxRetries`. `request(input, options?)` está descrita
|
|
450
469
|
[acima](#request-chamada-bruta).
|
|
451
470
|
|
|
471
|
+
## Limitações confirmadas pelo fornecedor (TSMX, 06/11)
|
|
472
|
+
|
|
473
|
+
O que o suporte da TSMX (Erick Silva, 05/11; Natanael Azevedo, 06/11) afirmou que a API do SGP **não**
|
|
474
|
+
faz. São palavras do fornecedor, que o SDK não testa nem contorna; as evidências por cenário estão em
|
|
475
|
+
[COMPATIBILITY.md](COMPATIBILITY.md).
|
|
476
|
+
|
|
477
|
+
- **Segundo contrato em cliente definitivo:** sem API ("No momento não seria possível adicionar um
|
|
478
|
+
segundo contrato em cadastros definitivos via API").
|
|
479
|
+
- **Telefonia:** sem API para adicionar o serviço ("No momento não temos end-points para adicionar
|
|
480
|
+
serviços de telefonia").
|
|
481
|
+
- **Serviços extras:** pela API só TV (`services.addTv`) e genérico (`services.addGeneric`); internet
|
|
482
|
+
adicional (como locação de roteador) e multimídia, só pelo painel.
|
|
483
|
+
- **"Alterar Titular" e migração de contrato:** sem rota de API (constatação nossa nas rotas
|
|
484
|
+
sondadas; a TSMX não respondeu essa pergunta de forma explícita).
|
|
485
|
+
- **Documentação oficial:** só a coleção do Postman; não há Swagger/OpenAPI.
|
|
486
|
+
- **CNPJ alfanumérico e tipos `E`/`EJ`:** os filtros `cpfcnpj` de leitura aceitam um CNPJ
|
|
487
|
+
alfanumérico (constatação nossa, observada ao vivo, só leitura: resposta normal, sem rejeição de formato; nenhum
|
|
488
|
+
achado foi observado). A criação de PJ com ele não foi testada, e para
|
|
489
|
+
`/E` e `/EJ` o fornecedor não tem exemplo que funcione. Detalhes em
|
|
490
|
+
[COMPATIBILITY.md](COMPATIBILITY.md).
|
|
491
|
+
- **Planos:** os IDs de plano do pré-cadastro e do cliente definitivo são diferentes de propósito e
|
|
492
|
+
nenhuma rota devolve a correspondência; o consumidor casa pela descrição.
|
|
493
|
+
|
|
452
494
|
## Migração do 1.x
|
|
453
495
|
|
|
454
496
|
A 2.0 é uma quebra de contrato (resultado, códigos, nomes e comportamento), sem aliases. O mapa de
|