● Como Usar o SAP Service Layer no Servidor da Cia do Sorriso
---
Dados de Acesso
┌─────────────────┬───────────────────────────────────┐
│ Item │ Valor │
├─────────────────┼───────────────────────────────────┤
│ URL Base │ https://172.100.0.17:50000/b1s/v2 │
├─────────────────┼───────────────────────────────────┤
│ Versao API │ v2 (NUNCA usar v1) │
├─────────────────┼───────────────────────────────────┤
│ Company DB │ SBO_CiadoSorriso │
├─────────────────┼───────────────────────────────────┤
│ Usuario │ manager │
├─────────────────┼───────────────────────────────────┤
│ Certificado SSL │ Auto-assinado (usar verify=False) │
└─────────────────┴───────────────────────────────────┘
---
1. Login (Obter Sessao)
Toda interacao com o Service Layer comeca com login. Retorna um SessionId que deve
ser enviado como cookie em todas as requisicoes seguintes.
curl -k -X POST "https://172.100.0.17:50000/b1s/v2/Login" \
-H "Content-Type: application/json" \
-d '{
"CompanyDB": "SBO_CiadoSorriso",
"UserName": "manager",
"Password": "SUA_SENHA_AQUI"
}'
Resposta:
{
"SessionId": "abc123...",
"Version": "1000190",
"SessionTimeout": 300
}
Importante:
- O SessionId tambem vem no cookie B1SESSION
- O cookie ROUTEID pode vir junto (necessario em clusters)
- Timeout: 300 segundos (5 min) de inatividade = sessao expira
- No sistema de producao, a sessao e armazenada no Redis (chave SessionIdSAP, TTL
280s)
---
2. Fazendo Requisicoes Autenticadas
Apos login, envie o B1SESSION como cookie:
# GET - Listar itens
curl -k -X GET
"https://172.100.0.17:50000/b1s/v2/Items?\$top=5&\$select=ItemCode,ItemName" \
-b "B1SESSION=abc123..."
# POST - Criar Business Partner
curl -k -X POST "https://172.100.0.17:50000/b1s/v2/BusinessPartners" \
-H "Content-Type: application/json" \
-b "B1SESSION=abc123..." \
-d '{
"CardCode": "C999999",
"CardName": "Teste API",
"CardType": "cCustomer"
}'
# PATCH - Atualizar Business Partner
curl -k -X PATCH "https://172.100.0.17:50000/b1s/v2/BusinessPartners('C999999')" \
-H "Content-Type: application/json" \
-b "B1SESSION=abc123..." \
-d '{"Phone1": "81999999999"}'
---
3. Endpoints Usados no Sistema
Endpoint: /Login
Metodo: POST
Descricao: Autenticacao
────────────────────────────────────────
Endpoint: /Logout
Metodo: POST
Descricao: Encerrar sessao
────────────────────────────────────────
Endpoint: /BusinessPartners
Metodo: GET/POST/PATCH
Descricao: Clientes (CardType=C) e Fornecedores/Dentistas (CardType=S)
────────────────────────────────────────
Endpoint: /Orders
Metodo: GET/POST
Descricao: Pedidos de Venda (ORDR)
────────────────────────────────────────
Endpoint: /DownPayments
Metodo: GET/POST
Descricao: Adiantamentos (ODPI)
────────────────────────────────────────
Endpoint: /IncomingPayments
Metodo: GET/POST
Descricao: Recebimentos (ORCT)
────────────────────────────────────────
Endpoint: /Items
Metodo: GET
Descricao: Consulta de Itens
────────────────────────────────────────
Endpoint: /JournalEntries
Metodo: POST
Descricao: Lancamentos Contabeis Manuais (LCM)
────────────────────────────────────────
Endpoint: /InventoryGenEntries
Metodo: POST
Descricao: Entrada de Mercadoria
────────────────────────────────────────
Endpoint: /ProfitCenters
Metodo: GET/POST/PATCH
Descricao: Centros de Custo
────────────────────────────────────────
Endpoint: /CreditCards
Metodo: GET
Descricao: Cartoes de Credito cadastrados
────────────────────────────────────────
Endpoint: /Series
Metodo: GET
Descricao: Series de numeracao
---
4. Fluxo Documental (CRITICO)
O sistema cria documentos nesta ordem obrigatoria:
Recebimento PV
|
v
Pedido de Venda (ORDR) POST /Orders
|
v
Adiantamento (ODPI) POST /DownPayments
| (BaseType=17, BaseEntry=DocEntry do ORDR)
v
Recebimento (ORCT) POST /IncomingPayments
(InvoiceType=it_DownPayment, DocEntry do ODPI)
---
5. Query Parameters (OData)
O Service Layer suporta OData v4:
$top=10 # Limitar resultados
$skip=20 # Pular registros (paginacao)
$select=CardCode,CardName # Selecionar campos
$filter=CardType eq 'cCustomer' # Filtrar
$orderby=CardCode desc # Ordenar
$count=true # Contar total
Exemplos de filtros:
# Buscar cliente por CPF (campo Password no SAP)
$filter=Password eq '12345678901' and CardType eq 'cCustomer'
# Centros de custo da dimensao 2 (dentistas)
$filter=InWhichDimension eq 2
# Pedidos de um cliente
$filter=CardCode eq 'C00001'
---
6. Testando Conexao no Servidor
Via API do sistema:
# Testar conexao SAP
curl http://localhost:8000/api/v1/integracao/testar-sap-connection
# Health check SAP
curl http://localhost:8000/api/v1/sap-status/health
Via Python (dentro do container backend):
from app.services.sap_service_layer import sap_service_layer
# Login
session = await sap_service_layer.login()
# GET
result = await sap_service_layer.get("/Items", {"$top": 1})
# POST com retry automatico (3 tentativas, backoff 2s/4s/8s)
result = await sap_service_layer.post("/BusinessPartners", payload)
# PATCH com retry
result = await sap_service_layer.patch("/BusinessPartners('C00001')", payload)
# Metodos de alto nivel
result = await sap_service_layer.criar_cliente({...})
result = await sap_service_layer.criar_pedido_venda({...})
result = await sap_service_layer.criar_adiantamento({...})
result = await sap_service_layer.criar_recebimento({...})
result = await sap_service_layer.criar_lancamento_contabil({...})
---
7. Gerenciamento de Sessao (Redis)
O sistema usa Redis para compartilhar a sessao SAP entre todas as requisicoes:
┌──────────────┬───────────────────────────────────────────┬──────┐
│ Chave Redis │ Valor │ TTL │
├──────────────┼───────────────────────────────────────────┼──────┤
│ SessionIdSAP │ JSON com session_id, route_id, expires_at │ 280s │
└──────────────┴───────────────────────────────────────────┴──────┘
- Se a sessao expira (erro 401/403), o sistema faz login automatico
- Apenas 1 worker Uvicorn em producao (multiplos workers quebram sessao)
- Nunca armazene sessao apenas em memoria
---
8. Tratamento de Erros
┌─────────────┬──────────────────────────────────┬────────────────────┐
│ Status │ Significado │ Acao │
├─────────────┼──────────────────────────────────┼────────────────────┤
│ 200/201 │ Sucesso │ Processar resposta │
├─────────────┼──────────────────────────────────┼────────────────────┤
│ 204 │ Sucesso sem corpo (PATCH/DELETE) │ OK │
├─────────────┼──────────────────────────────────┼────────────────────┤
│ 401/403 │ Sessao expirada │ Auto-renovacao │
├─────────────┼──────────────────────────────────┼────────────────────┤
│ 400 │ Erro de validacao SAP │ Verificar payload │
├─────────────┼──────────────────────────────────┼────────────────────┤
│ 500/502/503 │ Erro temporario │ Retry automatico │
└─────────────┴──────────────────────────────────┴────────────────────┘
O metodo request_with_retry() faz ate 3 tentativas com backoff exponencial (2s, 4s,
8s) para erros temporarios e timeouts.
---
9. Mapeamentos Importantes
Conceito PV: Paciente codigo
Campo SAP: OCRD.AliasName (CardType=C)
Endpoint: /BusinessPartners
────────────────────────────────────────
Conceito PV: Dentista codigo
Campo SAP: OCRD.AliasName (CardType=S)
Endpoint: /BusinessPartners
────────────────────────────────────────
Conceito PV: Item codigo
Campo SAP: OITM.SWW
Endpoint: /Items
────────────────────────────────────────
Conceito PV: CPF paciente
Campo SAP: OCRD.Password
Endpoint: /BusinessPartners
────────────────────────────────────────
Conceito PV: Unidade
Campo SAP: BPL (Branch)
Endpoint: Tabela integracao.unidades_config
Servicos vs Produtos:
- Codigo comeca com "I" = Produto → BPL 6 (MaxCare), deposito_produtos_whs
- Outros (P, M, D) = Servico → BPL da unidade, deposito_materiais_whs
---
Documentacao Oficial SAP Service Layer
- https://help.sap.com/doc/056f69366b5345a386bb8149f1700c19/10.0/en-US/Service%20La
yer%20API%20Reference.html
- [SAP Business One Service Layer - SAP Help
Portal](https://help.sap.com/docs/SAP_BUSINESS_ONE/7f234e5ed
tried/ef5eca93473b4c71a3e5e6e3db61801c.html)
- https://community.sap.com/topics/business-one
- Swagger local (quando debug=True): https://172.100.0.17:50000/b1s/v2/help