Fullstore
Documentação técnica da integração entre o isnapp e a plataforma FullStore. Destinada à equipe de T.I. responsável pela manutenção, suporte e diagnóstico do serviço.
Token do serviço: /bibliotecas/ba4e7bb5-4770-4780-beaa-b28980153cc7/wosk/webservice/fullStoreService
Namespace: WOSK\fullStoreService
- Visão Geral
- Arquitetura e Tecnologias
- Fluxo Funcional
- Canal PDV — Vendas
- Canal Trocas e Devoluções
- Canal Omni
- Canal E-commerce
- API — Parâmetros e Resposta
- Configuração e Dependências
- Troubleshooting e Testes
Visão Geral
O que consolidamos
Nossa integração coleta dados de vendas de quatro canais distintos e os entrega à FullStore em um único JSON estruturado, permitindo que a plataforma calcule comissões e analise o desempenho de cada vendedor sem precisar acessar diretamente os bancos de dados internos.
PDV
Vendas realizadas no balcão da loja física, com itens e NF-e.
Trocas
Devoluções e trocas vinculadas à NF da venda original.
Omni
Pedido criado pelo vendedor na loja com entrega em domicílio ou retirada em outra unidade.
E-commerce
Pedidos do site processados pelo sistema Linx (SQL Server).
Sistemas envolvidos
| Sistema | Papel | Banco |
|---|---|---|
| ERP OSK (loja) | Fonte de dados — PDV, Trocas, Omni | MySQL |
| Linx | Fonte de dados — E-commerce e BI | SQL Server LX_ZERO_300 |
| FullStore | Consumidora da API | — |
Ação disponível
Disponibilizamos uma única ação: getVendas. Ela recebe CNPJ da loja e intervalo de datas, consulta os quatro canais em sequência e retorna tudo consolidado.
Estrutura da resposta
{
"success": true,
"message": "Vendas retornadas com sucesso!",
"data": {
"vendas": [ /* PDV — vendas com itens agrupados */ ],
"trocas": [ /* Trocas agrupadas por NF original */ ],
"omni": [ /* Pedidos omni com entrega/retirada */ ],
"vendas_ecommerce": [ /* Pedidos e-commerce vindos do SQL Server */ ],
"fallback": null /* Preenchido se o período exceder o limite */
}
}
Restrições de período
LIMITE_DIAS_CONSULTA = 200). Se dataInicio ou dataFim estiver além desse limite, retornamos success: true com todos os arrays vazios e o objeto fallback preenchido com os parâmetros recebidos — sem erro de sistema.cnpjLoja é obrigatório e filtra todos os canais. Sem ele, a requisição falha na validação antes de qualquer consulta ao banco.Arquitetura e Tecnologias
Stack técnico, hierarquia de classes, dependências e conexões com bancos de dados.
Diagrama de componentes
Stack
| Camada | Tecnologia | Detalhe |
|---|---|---|
| Linguagem | PHP 7.3 | Namespaces, PDO, Traits |
| Framework | CodeIgniter (MY_Controller) |
Base do backend |
| Banco operacional | MySQL / PDO | PDV, Omni, Trocas |
| Banco E-commerce | SQL Server / PDO sqlsrv: |
Linx LX_ZERO_300 |
| Resposta | JSON via setSubmit() |
Envelope padrão success / message / data |
Hierarquia de classes
Arquivos required
Em controle.php, carregamos três dependências via require_once(APPPATH . '...'):
| UUID | Arquivo | Fornece |
|---|---|---|
4cb18a6c-... |
wosk_webservice.php |
Trait WOSK\Commons\WebService — formata JSON (setSubmit), valida campos e salva logs no MySQL |
592ccfa0-... |
utilOsk.php |
Classe pai — conecta ao MySQL OSK e expõe $this->conexao (PDO) |
0670acec-... |
db_sqlserver.php |
Gerencia conexão PDO com SQL Server (driver sqlsrv:) |
Conexão MySQL
A classe utilOsk chama getConfiguracao('db_osk_prod') — credenciais armazenadas em Base64 na tabela de configuração do sistema. Em seguida, _setConexao() cria a conexão PDO:
// connection string:
"mysql:host={host};port={porta};dbname={banco}"
// PDO::ATTR_PERSISTENT = true (conexão persistente)
// PDO::ATTR_TIMEOUT = 120 (timeout em segundos)
// charset = UTF-8
Conexão SQL Server
$sqlserver = new \db_sqlserver(false, 'LX_ZERO_300', true);
// false = produção (não homologação)
// 'LX_ZERO_300' = banco Linx
// true = conecta imediatamente
| Ambiente | Host | Porta | Banco |
|---|---|---|---|
| Produção | <HOST_SQLSERVER_PROD> |
<PORTA_PROD> |
LX_ZERO_300 |
| Homologação | <HOST_SQLSERVER_HML> |
<PORTA_HML> |
LINX_HMLG |
db_sqlserver.php. Tabelas MySQL utilizadas
| Tabela | Alias | O que fornece |
|---|---|---|
movimentacao |
m | Cabeçalho da transação (tipo, data, situação, módulo) |
movimentacao_detalhe |
md | Itens da venda (produto, qtde, preço) |
movimentacao_nfe |
nf / nfe | Número, série e situação da NF-e |
movimentacao_movimentacao |
mm | Vínculos entre movimentações (troca↔venda, omni↔orçamento) |
pessoa |
v | Nome e código do vendedor |
entidade |
e | Código da filial / loja |
juridica |
j | CNPJ da empresa |
Objetos SQL Server utilizados
| Objeto | Tipo | O que fornece |
|---|---|---|
W_BI_FAT_VENDEDOR_VDK_OMNI_V0 |
View BI | Pedidos e-commerce por vendedor: NF, valor, CPF, filial, pedido site/WMS |
FILIAIS |
Tabela | Cadastro de filiais — usamos para excluir franquias (TIPO_FILIAL <> 'FRANQUIA') |
Fluxo Funcional
Passo a passo de uma requisição, validações e tratamento de erros.
Diagrama de sequência
Diagrama de fluxo (decisões)
Passo a passo detalhado
- Recebimento da requisição
Recebemos o payload viarun(array $params). O parâmetroacaodeve ser'getVendas'; qualquer outro valor resulta em erro imediato. - Validação de parâmetros
Validamos viavalidarParametrosObrigatorios():dataInicio,dataFimecnpjLoja— presença e valor não vazio. Se algum faltar, lançamos uma exception com o nome do campo faltante. - Normalização do período
VianormalizarPeriodo(), adicionamos horários às datas: início ficadataInicio 00:00:00e fimdataFim 23:59:59, garantindo cobertura integral dos dias extremos. - Verificação do limite
ViaperiodoExcedeLimite(), checamos se alguma das datas está além de 200 dias no passado. Se sim,getVendasConsolidadas()monta arrays vazios e um objetofallback, masrun()ainda trata o resultado como nenhum registro encontrado e retorna erro ao consumidor. - Vendas PDV
Executamos query com 2 CTEs nas tabelasmovimentacao + movimentacao_detalhe + movimentacao_nfe. Retornamos uma linha por item e depois agrupamos poridentificadorviaagruparItensDasVendas(), gerando o sub-arrayitens. - Trocas
Buscamos movimentações de entrada comtipo_estoque = 'TROCA', vinculando à venda original viamovimentacao_movimentacao. Consolidamos múltiplas trocas do mesmo documento somando valores emagruparTrocasPorDocumento(). - Omni
Buscamos pedidos omni criados pelo vendedor na loja (orçamentos comtipo_estoque = 'ORCAMENTO'e situação Confirmado/Finalizado), vinculados à venda real viamovimentacao_movimentacao. - E-commerce
Em dois sub-passos: (1) resolvemos os códigos de filial ativas via MySQL/CNPJ; (2) consultamos a view SQL Server com placeholders paramétricos dinâmicos para cada filial. - Resposta
Montamos o objetodatacom os quatro arrays e retornamos viasetSubmit(true, 'Vendas retornadas com sucesso!', $data).
Tratamento de erros
| Situação | Comportamento | success |
|---|---|---|
| Parâmetro obrigatório ausente | Mensagem com nome do campo faltante | false |
| Ação inválida (≠ getVendas) | Mensagem de ação não encontrada | false |
| Período além de 200 dias | Fallback interno é montado, mas a resposta final atual é erro de nenhum registro | false |
| CNPJ sem filiais ativas no MySQL | vendas_ecommerce vazio; se os demais canais também estiverem vazios, retorna erro de nenhum registro |
Depende |
| Falha no SQL Server | Exception capturada → retorno false |
false |
Parâmetro falha enviado |
Força erro (uso em testes) | false |
wosk_webservice* do banco integrador. Em caso de disputa ou diagnóstico, basta consultar wosk_webservice_retorno pelo timestamp.Canal PDV — Vendas
Capturamos as vendas registradas no módulo PDV — transações de saída com NF-e autorizada/cancelada quando existir vínculo em movimentacao_nfe. Cada venda pode ter um ou mais itens; nossa query retorna uma linha por item e o método agruparItensDasVendas() os agrupa em um array aninhado itens.
Métodos: consultarVendasPdv() → agruparItensDasVendas()
Relacionamento das tabelas
Filtros aplicados
| Campo | Valor / Condição | Motivo |
|---|---|---|
m.modulo |
= 'PDV' |
Apenas transações do módulo de caixa |
m.tipo |
= 'SAIDA' |
Apenas saídas (vendas) |
m.situacao |
<> 'Cancelado' |
Excluímos movimentações canceladas no cabeçalho |
m.data_emissao |
BETWEEN :dataInicio AND :dataFim |
Filtro de período normalizado |
j.cnpj |
= :cnpjLoja |
Restringe à loja da requisição |
nf.situacao |
IN ('AUTORIZADO','CANCELADO') |
NF-e com situação definida no SEFAZ |
md.situacao |
= 'ATIVO' |
Apenas linhas de detalhe ativas |
Estrutura da query (2 CTEs)
- movimentacoes — agrupa dados do cabeçalho: vendedor, NF-e, entidade, CNPJ
- itens — junta os detalhes de produto aos cabeçalhos
O SELECT final une os dois CTEs retornando uma linha por item, depois agrupamos em PHP.
Retorno da API
// Um elemento do array "vendas"
{
"codigo_cliente": 123,
"cod_vendedor": "V001",
"cnpj_emp": "12345678000190",
"data_documento": "2026-05-15T10:30:00-03:00", // ISO 8601
"identificador": 9001,
"transacao": 9001,
"usuario": 42,
"documento": "000001234", // Número NF-e
"serie": "001",
"operacao": "S",
"tipo_transacao": "VENDA", // Fixo neste canal
"cancelado": "N", // Derivado de movimentacao.situacao; na query atual tende a "N"
"delivery": false,
"itens": [
{
"cod_produto": "PROD-001",
"descricao_produto": "Camiseta Branca M",
"cod_barra": "7891234567890",
"quantidade": 2,
"preco_unitario": 89.90,
"valor_total": 179.80
}
]
}
Dicionário de campos
| Campo | Origem no banco | Descrição |
|---|---|---|
identificador |
movimentacao.id |
Chave da venda — usada no agrupamento |
data_documento |
movimentacao.data_emissao |
Data/hora da venda em ISO 8601 |
cod_vendedor |
pessoa.codigo |
Código do vendedor responsável |
codigo_cliente |
movimentacao.id_pessoa |
ID do cliente |
cnpj_emp |
juridica.cnpj |
CNPJ da loja |
documento |
movimentacao_nfe.numero |
Número da NF-e |
serie |
movimentacao_nfe.serie |
Série da NF-e |
cancelado |
Derivado de movimentacao.situacao |
Como a query filtra m.situacao <> 'Cancelado', na prática tende a "N" |
tipo_transacao |
Hardcoded | Sempre "VENDA" neste canal |
itens[].cod_barra |
movimentacao_detalhe.codigo_ean |
EAN do produto |
itens[].valor_total |
movimentacao_detalhe.valor_rateio |
Valor rateado retornado como total do item |
cancelado é calculado a partir de movimentacao.situacao, não de movimentacao_nfe.situacao; portanto, NF-e cancelada pode aparecer no join, mas esse cancelamento não altera automaticamente o flag retornado.Canal Trocas e Devoluções
Capturamos movimentações de entrada do tipo TROCA. Quando o cliente devolve ou troca uma peça, o sistema OSK registra uma nova movimentação de entrada e a vincula à venda original via tabela movimentacao_movimentacao.
Métodos: getTrocas() → agruparTrocasPorDocumento()
Vínculo troca ↔ venda original
Filtros aplicados
| Campo | Valor | Motivo |
|---|---|---|
m.modulo |
'PDV' |
Apenas trocas do PDV |
m.tipo |
'ENTRADA' |
Mercadoria retornando ao estoque |
m.tipo_estoque |
'TROCA' |
Distingue de compras e outras entradas |
m.situacao |
'FINALIZADO' |
Apenas trocas concluídas |
m.data_emissao |
BETWEEN :dataInicio AND :dataFim |
Período da requisição |
j.cnpj |
= :cnpjLoja |
Restringe à loja |
Estrutura da query (3 CTEs)
- e — filtra a entidade (loja) pelo CNPJ informado
- m — agrega movimentações de troca: soma valores e quantidades por movimentação
- tr — junta ao documento original via
movimentacao_movimentacaoe busca a NF de venda
Agrupamento por documento
A mesma NF pode ter múltiplas trocas (cliente troca um item hoje e outro amanhã). Em agruparTrocasPorDocumento() consolidamos assim:
- Somamos
valor_valeevalor_original - A implementação atual não soma
quantidadeao agrupar documentos repetidos; mantém a quantidade do primeiro registro do grupo - Mantemos o timestamp mais recente
- Trocas sem vínculo com NF original são incluídas individualmente
Retorno da API
// Um elemento do array "trocas"
{
"motivo": "Defeito no produto",
"doc_venda": "000001234", // NF da venda original
"serie_venda": "001",
"cod_cliente": 123,
"cnpj_emp": "12345678000190",
"valor_vale": 89.90, // Crédito gerado para o cliente
"valor_original": 89.90, // Mesmo valor agregado da troca na implementação atual
"timestamp": "2026-05-18T14:22:00-03:00",
"cod_vendedor": "V001",
"quantidade": 1
}
Dicionário de campos
| Campo | Origem | Descrição |
|---|---|---|
doc_venda |
movimentacao_nfe.numero da venda |
NF da venda que originou a troca |
serie_venda |
movimentacao_nfe.serie da venda |
Série da NF original |
valor_vale |
Soma dos itens da troca | Crédito gerado para o cliente |
valor_original |
SUM(md.valor_rateio) da movimentação de troca |
Na implementação atual, recebe o mesmo agregado usado em valor_vale |
timestamp |
movimentacao.data_emissao |
Data/hora da troca — ISO 8601 |
cod_vendedor |
pessoa.codigo |
Vendedor que registrou a troca |
quantidade |
SUM(md.qtde) por movimentação de troca |
Não é acumulado novamente quando múltiplas trocas são agrupadas pelo mesmo documento |
doc_venda nulo), ela é incluída individualmente sem agrupamento. Isso ocorre quando a venda foi feita antes da implantação do controle de vínculos no sistema.Canal Omni
Pedido criado pelo vendedor na loja física com entrega em domicílio ou retirada em outra unidade.
2b74ab7 ("IMPLEMENTACAO VENDA OMNI"). É o canal com a lógica mais complexa do endpoint, usando 4 CTEs e um SELECT final.Fluxo do pedido omni
O cliente vai fisicamente até a loja. O vendedor, usando o sistema, cria o pedido pelo site (plataforma de e-commerce VTEX). A partir daí, existem duas possibilidades de fulfillment:
- Cliente vai à loja
Vendedor atende o cliente presencialmente e registra o pedido no sistema via plataforma web. - Pedido criado pelo site
O sistema gera um orçamento (tipo_estoque = 'ORCAMENTO') comid_tipo_movimentacao = 6eid_grupo_operacao = 192. - Fulfillment: Entrega em domicílio
O produto é despachado para o endereço do cliente — a venda real é registrada como saída no sistema e vinculada ao orçamento viamovimentacao_movimentacao. - Fulfillment: Retirada em outra unidade
O cliente retira o produto em uma loja diferente da que realizou a venda — o pedido transita entre unidades antes de ser entregue.
Identificadores do canal omni
Identificamos os pedidos omni pela combinação de três campos em movimentacao:
| Campo | Valor | Significado |
|---|---|---|
id_grupo_operacao |
192 |
Grupo de operação exclusivo do canal omni |
id_tipo_movimentacao |
6 |
Tipo de movimentação omni |
tipo_estoque |
'ORCAMENTO' |
Registrado como orçamento — não movimenta estoque diretamente |
situacao |
'Confirmado' ou 'Finalizado' |
Buscamos apenas pedidos que resultaram em venda real |
Estrutura da query (4 CTEs)
- e — filtra a entidade (loja) pelo CNPJ
- orcamento — busca orçamentos omni confirmados/finalizados no período
- mm — busca vínculos em
movimentacao_movimentacaopara localizar a venda real (SAIDA) - i — busca os itens do orçamento via
movimentacao_detalhena implementação atual - SELECT final — une orçamento + vendedor + itens
Retorno da API
// Um elemento do array "omni"
{
"id_cliente": 456,
"cod_vendedor": "V007",
"cnpj_emp": "12345678000190",
"data_documento": "2026-05-20 16:45:00", // Data da venda vinculada, sem conversão ISO no método atual
"id_pessoa": 88, // ID do vendedor em pessoa
"identificador": 3001, // ID da movimentação de venda vinculada
"transacao": 3001,
"usuario": 42,
"documento": "ORÇ-00321",
"vendedor": "João Silva", // Nome completo do vendedor
"cancelado": "N",
"itens": [
{
"cod_produto": "PROD-099",
"descricao_produto": "Tênis Running 42",
"cod_barra": "7896543219870",
"quantidade": 1,
"preco_unitario": 349.90,
"valor_total": 349.90
}
]
}
movimentacao_movimentacao, mas a CTE i busca os itens do orçamento (i.id_movimentacao = orcamento.id_movimentacao). Como o join com os itens é interno, se o orçamento não tiver itens ativos o registro omni não é retornado.Canal E-commerce
Consulta ao SQL Server (Linx) e mapeamento de colunas para o padrão FullStore.
Coletamos pedidos do e-commerce processados pelo sistema Linx. Esses dados ficam em um SQL Server separado (LX_ZERO_300), em uma view que já consolida faturamento por vendedor. Nosso processo ocorre em dois passos.
Métodos: buscarDadosEcommercePorLoja() → getVendasEcommerce()
Diagrama de sequência — dois passos
Mapeamento de colunas SQL Server → JSON
| Coluna SQL Server | Campo no JSON | Descrição |
|---|---|---|
CGC_CPF |
documento_cliente |
CPF/CNPJ do cliente |
VENDEDOR |
cod_vendedor |
Código do vendedor no Linx |
CUPOM_VENDEDOR |
cupom_vendedor |
Cupom aplicado pelo vendedor |
CODIGO_FILIAL |
codigo_filial |
Código da filial (padded com zeros) |
EMISSAO |
data_documento |
Data de emissão no formato retornado pelo SQL Server; o método atual não converte para ISO 8601 |
PEDIDO_SITE |
pedido_site |
Número do pedido no e-commerce |
PEDIDO_WMS |
pedido_wms |
Número do pedido no WMS |
TICKET |
ticket |
Ticket de atendimento |
NF |
documento |
Número da NF |
SERIE |
serie |
Série da NF |
VALOR_LIQUIDO |
valor |
Valor líquido do pedido |
QTDE_LIQUIDA |
qtde |
Quantidade líquida de itens |
rtrim() e ltrim() em todos os campos mapeados — o SQL Server da Linx pode devolver strings com espaços à esquerda ou direita.Retorno da API
// Um elemento do array "vendas_ecommerce"
{
"documento_cliente": "123.456.789-00",
"cod_vendedor": "EC001",
"cupom_vendedor": "VEND10OFF", // Pode ser string vazia
"codigo_filial": "000001",
"data_documento": "2026-05-22 09:15:00",
"pedido_site": "PS-98765",
"pedido_wms": "WMS-54321",
"ticket": "TKT-11111",
"documento": "000005678",
"serie": "001",
"valor": "259.90",
"qtde": "2"
}
Segurança — placeholders dinâmicos
O número de filiais varia por CNPJ. Em vez de concatenar valores na query, geramos placeholders e usamos bindValue() para cada um:
// Geração dos placeholders (PHP 7.3)
$placeholders = [];
foreach ($filiais as $i => $codigo) {
$key = ':filial' . $i;
$placeholders[] = $key;
$stmt->bindValue($key, $codigo);
}
// Resultado na query: IN (:filial0, :filial1, :filial2)
// Nenhum valor externo é interpolado na string SQL.
bindParam() e códigos de filial com bindValue(). Nenhuma concatenação de input externo ocorre.buscarDadosEcommercePorLoja() retorna um envelope de erro quando não encontra filial ativa no MySQL, mas getVendasConsolidadas() consome apenas a chave data. Na resposta final, isso aparece como vendas_ecommerce: []; se os demais canais também estiverem vazios, o endpoint retorna erro de nenhum registro.API — Parâmetros e Resposta
Especificação completa de getVendas: entrada, saída, erros e exemplos JSON.
Identificação do serviço
Token: <TOKEN_FULLSTORE>
Método HTTP: POST | Formato: JSON
BaseUrl: HTTPS://SEUSISTEMA.PDV.MODA/bibliotecas/ba4e7bb5-4770-4780-beaa-b28980153cc7/wosk/webservice/fullStoreService
Payload de entrada
{
"acao": "getVendas",
"key":" CHAVE API FORNECIDA",
"parametros": {
"dataInicio": "2026-03-10",
"dataFim": "2026-03-10",
"cnpjLoja": ""
}
}
| Campo | Tipo | Formato | Obrig. | Descrição |
|---|---|---|---|---|
acao |
string | literal | Sim | Deve ser exatamente "getVendas" |
parametros.dataInicio |
string | Y-m-d |
Sim | Início do período. Ex: "2026-05-01" |
parametros.dataFim |
string | Y-m-d |
Sim | Fim do período. Ex: "2026-05-31" |
parametros.cnpjLoja |
string | 14 dígitos | Sim | CNPJ sem máscara — filtra todos os canais |
falha |
any | — | Teste | Se presente e não nulo, forçamos retorno de erro |
dataInicio ou dataFim estiver além de 200 dias no passado, a implementação atual monta um fallback interno, mas a resposta final retorna success: false com mensagem de nenhum registro encontrado.Resposta de sucesso (com dados)
{
"success": true,
"message": "Vendas retornadas com sucesso!",
"data": {
"vendas": [
{
"codigo_cliente": 123, "cod_vendedor": "V001",
"cnpj_emp": "12345678000190",
"data_documento": "2026-05-15T10:30:00-03:00",
"identificador": 9001, "transacao": 9001, "usuario": 42,
"documento": "000001234", "serie": "001",
"operacao": "S", "tipo_transacao": "VENDA",
"cancelado": "N", "delivery": false,
"itens": [
{ "cod_produto": "PROD-001", "descricao_produto": "Camiseta Branca M",
"cod_barra": "7891234567890", "quantidade": 2,
"preco_unitario": 89.90, "valor_total": 179.80 }
]
}
],
"trocas": [
{
"motivo": "Defeito", "doc_venda": "000001234", "serie_venda": "001",
"cod_cliente": 123, "cnpj_emp": "12345678000190",
"valor_vale": 89.90, "valor_original": 179.80,
"timestamp": "2026-05-18T14:22:00-03:00",
"cod_vendedor": "V001", "quantidade": 1
}
],
"omni": [
{
"id_cliente": 456, "cod_vendedor": "V007",
"cnpj_emp": "12345678000190",
"data_documento": "2026-05-20 16:45:00",
"id_pessoa": 88, "identificador": 3001, "transacao": 3001, "usuario": 42,
"documento": "ORÇ-00321", "vendedor": "João Silva", "cancelado": "N",
"itens": [
{ "cod_produto": "PROD-099", "descricao_produto": "Tênis Running 42",
"cod_barra": "7896543219870", "quantidade": 1,
"preco_unitario": 349.90, "valor_total": 349.90 }
]
}
],
"vendas_ecommerce": [
{
"documento_cliente": "123.456.789-00", "cod_vendedor": "EC001",
"cupom_vendedor": "VEND10OFF", "codigo_filial": "000001",
"data_documento": "2026-05-22 09:15:00",
"pedido_site": "PS-98765", "pedido_wms": "WMS-54321",
"ticket": "TKT-11111", "documento": "000005678",
"serie": "001", "valor": "259.90", "qtde": "2"
}
],
"fallback": null
}
}
Resposta — período excede o limite
{
"success": false,
"message": "Nenhum registro encontrado no periodo 2025-01-01 - 2025-06-30 para o cnpj 12345678000190",
"data": null
}
Respostas de erro
Parâmetro obrigatório ausente
{ "success": false, "message": "O parametro dataInicio é obrigatorio", "data": null }
Ação inválida
{ "success": false, "message": "Acao nao encontrada", "data": null }
Nenhum dado no período
{
"success": false,
"message": "Nenhum registro encontrado no periodo 2026-05-01 - 2026-05-31 para o cnpj 12345678000190",
"data": null
}
Formato de datas
O formato de data varia por canal na implementação atual. PDV e Trocas convertem datas com date('c', strtotime($valor)). Omni e E-commerce retornam a data no formato vindo da consulta, sem conversão explícita para ISO 8601:
// PDV / Trocas
"data_documento": "2026-05-15T10:30:00-03:00"
// Omni / E-commerce
"data_documento": "2026-05-20 16:45:00"
Configuração e Dependências
Requires em controle.php
Carregamos três dependências via require_once(APPPATH . '...'):
require_once(APPPATH . 'controllers/bibliotecas/4cb18a6c-9c9a-4201-82e6-4f6cc3bea445/wosk_webservice.php');
require_once(APPPATH . 'controllers/bibliotecas/592ccfa0-2692-44e3-aaea-cc7c6c6cfcfa/utilOsk.php');
require_once(APPPATH . 'controllers/bibliotecas/0670acec-4aca-43a0-8943-659600407283/db_sqlserver.php');
| UUID | Arquivo | O que fornece |
|---|---|---|
4cb18a6c-... |
wosk_webservice.php |
Trait WOSK\Commons\WebService — formata JSON, valida campos e salva logs |
592ccfa0-... |
utilOsk.php |
Classe pai — conecta ao MySQL e expõe $this->conexao (PDO) |
0670acec-... |
db_sqlserver.php |
Gerencia a conexão PDO com o SQL Server Linx (driver sqlsrv:) |
Conexão MySQL
Em utilOsk, chamamos getConfiguracao('db_osk_prod') — as credenciais ficam em Base64 numa tabela de configuração do sistema. O método _setConexao() cria a conexão PDO:
// PHP 7.3 — connection string
"mysql:host={$host};port={$porta};dbname={$banco};charset=utf8"
PDO::ATTR_PERSISTENT = true // conexão persistente
PDO::ATTR_TIMEOUT = 120 // timeout em segundos
PDO::ATTR_EMULATE_PREPARES = true
Conexão SQL Server
// PHP 7.3
$sqlserver = new \db_sqlserver(false, 'LX_ZERO_300', true);
// Parâmetros: ($homologacao = false, $banco, $conectar_agora = true)
// connection string: "sqlsrv:Server=<HOST_SQLSERVER>,<PORTA>;Database=LX_ZERO_300"
| Ambiente | Host | Porta | Banco | Usuário |
|---|---|---|---|---|
| Produção | <HOST_SQLSERVER_PROD> |
<PORTA_PROD> |
LX_ZERO_300 |
<USUARIO_SQLSERVER> |
| Homologação | <HOST_SQLSERVER_HML> |
<PORTA_HML> |
LINX_HMLG |
<USUARIO_SQLSERVER> |
db_sqlserver.phpVariáveis de ambiente
| Variável | Usada por | Descrição |
|---|---|---|
$_ENV["base_db"] |
util |
Nome do banco MySQL principal |
$_ENV['WOSK_DB_HMG'] |
WOSK\Common |
Flag de homologação para conexões WOSK (false em produção) |
APPPATH |
controle.php |
Constante CodeIgniter — base dos require_once |
Logs de requisição
O trait WOSK\Commons\WebService salva automaticamente toda chamada no banco integrador ({base_db}_integrador):
| Tabela | Conteúdo |
|---|---|
wosk_webservice |
Registro principal da chamada |
wosk_webservice_parametros |
Parâmetros recebidos (JSON) |
wosk_webservice_retorno |
Resposta enviada (JSON) |
wosk_webservice_callback |
Tokens de callback |
wosk_webservice_retorno no banco integrador filtrando pelo timestamp e pelo token <TOKEN_FULLSTORE>.Troubleshooting e Testes
Problemas comuns, checklist de diagnóstico e como testar o endpoint manualmente.
Problemas comuns
1. vendas_ecommerce sempre retorna vazio
- O
cnpjLojanão tem entidades ativas no MySQL:SELECT e.* FROM entidade e JOIN juridica j ON e.id_pessoa=j.id WHERE j.cnpj='CNPJ' AND e.situacao='ATIVO' - A filial está como
TIPO_FILIAL = 'FRANQUIA'no SQL Server — excluímos franquias. - A view
W_BI_FAT_VENDEDOR_VDK_OMNI_V0não tem dados para o período/filial informados. - Falha na conexão SQL Server — verificar porta
1435e extensãopdo_sqlsrv.
2. Erro de nenhum registro por período além do limite
O período informado ultrapassa 200 dias no passado. A implementação atual monta um fallback internamente, mas a resposta final retorna success:false com mensagem de nenhum registro encontrado. Com a data de hoje 2026-06-09, o limite de calendário recua até 2025-11-21; por causa da comparação com horário atual, use 2025-11-22 como primeira data segura para evitar a borda.
// dataInicio: "2025-01-01" → excede → retorna success:false
// dataInicio: "2025-11-22" → dentro do limite com margem de segurança
3. Erro success: false — campo faltante
Verificar se o payload contém os três campos dentro de parametros: dataInicio, dataFim e cnpjLoja. Valores null ou string vazia também disparam a validação.
4. Trocas não aparecem mesmo com devoluções registradas
- A troca não está com
situacao = 'FINALIZADO'— buscamos apenas finalizadas. - O
tipo_estoquenão é'TROCA'— outros tipos de entrada são ignorados. - A data de emissão da troca está fora do período solicitado.
Checklist de diagnóstico
| # | Verificação | Comando / Query |
|---|---|---|
| 1 | MySQL acessível? | SELECT 1 via PDO |
| 2 | CNPJ existe em juridica? |
SELECT * FROM juridica WHERE cnpj = 'CNPJ' |
| 3 | CNPJ tem filiais ativas? | SELECT e.codigo FROM entidade e JOIN juridica j ON e.id_pessoa=j.id WHERE j.cnpj='CNPJ' AND e.situacao='ATIVO' |
| 4 | Existem vendas PDV no período? | SELECT COUNT(*) FROM movimentacao WHERE modulo='PDV' AND tipo='SAIDA' AND data_emissao BETWEEN '...' AND '...' |
| 5 | SQL Server acessível? | new \db_sqlserver(false, 'LX_ZERO_300', true) — exception = falha de conexão |
| 6 | View tem dados? | No SSMS: SELECT TOP 10 * FROM W_BI_FAT_VENDEDOR_VDK_OMNI_V0 WHERE EMISSAO >= 'data' |
| 7 | Log da requisição salvo? | SELECT * FROM wosk_webservice_retorno ORDER BY id DESC LIMIT 5 |
Como testar o endpoint
Via cURL
curl -X POST https://SEU_SERVIDOR/bibliotecas/<TOKEN_FULLSTORE> \
-H "Content-Type: application/json" \
-d '{
"acao": "getVendas",
"parametros": {
"dataInicio": "2026-05-01",
"dataFim": "2026-05-31",
"cnpjLoja": "12345678000190"
}
}'
Forçar erro (ambiente de testes)
{
"acao": "getVendas",
"falha": "teste",
"parametros": {
"dataInicio": "2026-05-01",
"dataFim": "2026-05-31",
"cnpjLoja": "12345678000190"
}
}
Interpretando a resposta
| Cenário | success | fallback | Arrays | Ação |
|---|---|---|---|---|
| Funcionamento normal | true | null |
Preenchidos | Processar normalmente |
| Sem movimento no período | false | — | — | Validar se realmente não há dados no período |
| Período além do limite | false | Não exposto na resposta atual | — | Ajustar datas da consulta |
| Parâmetro faltando | false | — | — | Corrigir payload |
| Falha de banco de dados | false | — | — | Verificar conectividade e logs PHP |
success antes de processar qualquer array. Na implementação atual, resposta sem nenhum registro retorna success:false; arrays vazios só aparecem quando pelo menos o envelope de dados é retornado.