Ir para o conteúdo principal

Protheus Nota Fiscal Marketplace Pontual (STATUS: PARCIAL)

Documentação Técnica

Nome do cliente TO-DO
Nome do projeto TO-DO
Biblioteca wosk_protheus_nota_fiscal_marketplace_pontual
Token da Biblioteca
b35dc71f-3153-423d-9bd2-3f97cbe66573
URL de Produção
https://isnapp.illimitar.pro/bibliotecas/b35dc71f-3153-423d-9bd2-3f97cbe66573/wosk_protheus_nota_fiscal_marketplace_pontual
URL de Homologação https://hmg-isnapp.illimitar.pro/bibliotecas/b35dc71f-3153-423d-9bd2-3f97cbe66573/wosk_protheus_nota_fiscal_marketplace_pontual
Data 23/02/2026

Sumário


    Histórico de Versões

    Data Versão Modificado por Descrição da Mudança
    23/02/2026 1.0 Maykon/Gustavo Documentação inicial

    Descrição Geral dos Processos

    Escopo deste arquivo:

    - Este documento foi gerado exclusivamente a partir de wosk_protheusNotaFiscalMarketplacePontual/wosk_protheusNotaFiscalMarketplacePontual.php.
    - Classes presentes neste arquivo: Monitor e Queue.
    - Classe ausente neste arquivo: Webservice (não há endpoint implementado aqui).

    Monitor

    Processo: 
    1. DESCRIÇÃO DO FLUXO

    - Responsabilidade: capturar, de forma incremental, notas fiscais do Marketplace (cabeçalho e itens) a partir de fontes SQL e enfileirar cada nota fiscal para processamento assíncrono.
    - Disparo: execução agendada (cron) chamando Monitor::run().

    Ao iniciar, o monitor determina o limite de paginação pela configuração woskLimiteCaptura::ProtheusNotaFiscalMarketplacePontual e carrega o estado persistido via get('ProtheusNotaFiscalMarketplacePontual'), contendo:
    - data_posicao, data_iniciado, offset, chave_posicao, filtro, token e situacao.

    Regras de continuidade:
    - Se situacao = 2 (Concluído) → redefine para 0 (Parado) e permite nova execução.
    - Se situacao estiver em [0, 1] → inicia/continua o processamento.

    Para a data base de captura, o monitor trabalha por janelas diárias. A cada ciclo de paginação ele:
    - Persiste situacao = 1 (Executando) antes da consulta.
    - Calcula dataInicio e dataFim como o intervalo do dia de filtro.DATA_PARA_TRANSFERENCIA (00:00:00 até 23:59:59).
    - Executa query paginada sobre WOSK_SERVICO_ENVIA_PROTHEUS_NOTA_OMNIMKTPLACE_PONTUAL filtrando por DATA_PARA_TRANSFERENCIA BETWEEN dataInicio AND dataFim, com:
        - ORDER BY DATA_PARA_TRANSFERENCIA ASC
        - OFFSET baseado no estado do monitor
        - FETCH NEXT no limite configurado

    Para cada nota fiscal retornada:
    - Sanitiza o cabeçalho com trim() recursivo.
    - Atualiza o filtro de posição (F2_FILIAL, F2_DOC, F2_SERIE, F2_CLIENTE, F2_LOJA, DATA_PARA_TRANSFERENCIA).
    - Monta a chave no padrão: F2_FILIAL-F2_DOC-F2_SERIE-F2_CLIENTE-F2_LOJA.
    - Consulta os itens via getItens(F2_FILIAL, F2_DOC, F2_SERIE, F2_CLIENTE, F2_LOJA), lendo de WOSK_SERVICO_ENVIA_PROTHEUS_NOTA_OMNIMKTPLACE_ITEM_PONTUAL.
    - Enfileira o registro (cabeçalho + itens) via Queue::set() com status Aguardando Integração e situacao = 0.
    - Atualiza incrementalmente o estado do monitor (offset, chave e data) após cada enfileiramento, garantindo retomada.

    Encerramento e agendamento da próxima janela (data):
    - Quando a página atual retorna menos registros que o limite, considera o dia processado e marca situacao = 2 (Concluído).
    - Se a data de posição for menor/igual ao momento atual, avança o filtro para o próximo dia (+1 dia) e redefine DATA_PARA_TRANSFERENCIA para 00:00:00 (reiniciando com offset = 0).

    Em caso de erro (catch):
    - Marca o monitor como situacao = 4 (Problema).
    - Registra a falha em filtro.ERRORS[] com DATE e MESSAGE.


    2. DADOS NECESSÁRIOS PARA O ENDPOINT

    Não há endpoint (WebService) implementado neste arquivo. Para o Monitor, os dados de entrada são originados das fontes SQL consultadas em viewQuery e getItens().

    Fonte (cabeçalho da nota):
    - View/Tabela lógica: WOSK_SERVICO_ENVIA_PROTHEUS_NOTA_OMNIMKTPLACE_PONTUAL
    Campos capturados:
    - Identificação/Chave: F2_FILIAL, F2_DOC, F2_SERIE, F2_CLIENTE, F2_LOJA
    - Controle: TIPO, E1_XFILORI, F2_PEDIDO, F2_TIPO, F2_FORMUL, F2_EMISSAO, F2_ESPECIE, F2_COND, F2_XNATOPE
    - NF-e: F2_CHVNFE, F2_HAUTNFE, F2_DAUTNFE, F2_PROTOCOLO
    - Valores: F2_FRETE, F2_SEGURO, F2_DESPESA, F2_XCBSIBS
    - Incremental: DATA_PARA_TRANSFERENCIA

    Fonte (itens da nota):
    - View/Tabela lógica: WOSK_SERVICO_ENVIA_PROTHEUS_NOTA_OMNIMKTPLACE_ITEM_PONTUAL
    Campos capturados:
    - Identificação: D2_ITEM, D2_COD, D2_TES
    - Quantidades/Valores: D2_QUANT, D2_PRCVEN, D2_TOTAL, D2_BASEICM, D2_PICM, D2_VALICM, D2_DESCON
    - Tributos adicionais: D2_XIBSBS, D2_XIBSAL, D2_XIBSVL, D2_XCBSBS, D2_XCBSAL, D2_XCBSVL
    - Incremental: DATA_PARA_TRANSFERENCIA


    3. REESTRUTURAÇÃO DOS DADOS

    3.1 Recuperação do estado do monitor
    Momento: Início do run()
    - Lê estado via get('ProtheusNotaFiscalMarketplacePontual').
    - Se estado estiver incompleto (sem data_posicao), inicializa: datas atuais, offset = 0, chave_posicao = '', filtro = [] e token = ''.

    3.2 Reset ao iniciar execução
    Momento: Quando situacao = 2 (pré-execução)
    - Persiste situacao = 0 com o estado atual para permitir novo ciclo.

    3.3 Normalização dos filtros
    Momento: Antes da query
    - Garante que F2_FILIAL, F2_DOC, F2_SERIE, F2_CLIENTE, F2_LOJA existam (string vazia quando ausentes).
    - Define DATA_PARA_TRANSFERENCIA:
        - informado → convertido/formatado para Y-m-d H:i:s
        - ausente → 2023-05-01 00:00:00

    3.4 Atualização do estado para EXECUTANDO
    Momento: Antes da consulta de cada página
    - Persiste situacao = 1 com o estado do monitor (offset, chave, datas, filtro).

    3.5 Paginação dos registros
    Momento: Execução da query
    - Query diária por intervalo (BETWEEN dataInicio AND dataFim).
    - Ordena por DATA_PARA_TRANSFERENCIA ASC.
    - Pagina com OFFSET/FETCH NEXT no limite configurado.

    3.6 Sanitização dos dados
    Momento: Ao ler cada registro (cabeçalho) e cada item (em getItens())
    - Aplica trim() recursivamente em todos os campos.

    3.7 Atualização do filtro de posição
    Momento: Após ler cada nota fiscal
    - Atualiza novoFiltro com a chave completa e a DATA_PARA_TRANSFERENCIA do registro (normalizada).

    3.8 Enfileiramento
    Momento: Dentro do loop de notas fiscais
    - Enfileira (cabeçalho + itens) via Queue::set() com:
        - chave: F2_FILIAL-F2_DOC-F2_SERIE-F2_CLIENTE-F2_LOJA
        - status: Aguardando Integração
        - situacao: 0

    3.9 Atualização incremental da posição
    Momento: Após inserir na fila
    - offsetoffset + 1
    - chavePosicao ← chave da nota fiscal
    - dataPosicaoDATA_PARA_TRANSFERENCIA
    - Persiste imediatamente para suportar retomada.

    3.10 Finalização
    Momento: Após encerrar o ciclo do dia
    - Se o dia foi concluído, agenda a próxima data (dia seguinte quando necessário) e persiste situacao = 2 com o novoFiltro efetivo.

    3.11 Tratamento de erro
    Momento: catch(Exception) do run()
    - Adiciona erro em filtro.ERRORS[] e persiste situacao = 4.


    4. PERSISTÊNCIA DOS DADOS (BANCO DE DADOS)

    4.1 Controle do monitor
    Momento: Durante execução, continuidade e finalização do run()
    - Persistência ocorre via Monitor::set() (trait wosk_monitor).
    - Tabela persistida: {$this->bancoIntegrador}.wosk_monitor.
    - Campos persistidos: token, evento, offset, filtro, chave_posicao, situacao, data_posicao, data_iniciado.

    4.2 Fila de integração
    Momento: Enfileiramento (3.8)
    - Tabela persistida: {$this->bancoIntegrador}.wosk_queue (via biblioteca wosk_queue).


    5. RESULTADO DO PROCESSAMENTO

    Execução normal:
    - Monitor marcado como Concluído (2) ao final do ciclo do dia.
    - Notas fiscais enfileiradas para envio ao Protheus pela Queue.

    Execução com erro:
    - Monitor marcado como Problema (4).
    - Erro persistido em filtro.ERRORS[] para auditoria e retomada controlada.


    6. OPERAÇÃO MANUAL – capturar()

    Objetivo: enfileirar manualmente uma ou mais notas fiscais a partir da chave completa.

    Fluxo:
    - Entrada: chave string ou array no padrão F2_FILIAL-F2_DOC-F2_SERIE-F2_CLIENTE-F2_LOJA.
    - Para cada chave:
        - Consulta Queue::get('', chave) para reaproveitar token quando existir.
        - Consulta a fonte por chave completa (WHERE com os 5 campos).
        - Sanitiza com trim() recursivo, carrega itens via getItens() e enfileira via Queue::set() usando o token reaproveitado.

    Queue

    Processo:
    1. DESCRIÇÃO DO FLUXO

    - Responsabilidade: consumir um item da fila, reestruturar/normalizar os dados (cabeçalho e itens), validar pré-condições e enviar a nota fiscal ao Protheus, persistindo retorno, tempo e status do processamento.
    - Disparo: execução agendada (cron) chamando Queue::run(token).

    Ao iniciar, a fila busca o item via get(token). Se houver registro:
    - Atualiza o item para status Enviando e situacao = 1 antes do envio.
    - Converte o conteúdo persistido em payload via getConteudo() aplicando o mapeamento definido em $field (inclui a estrutura itens).

    Pré-validação (dependência de cliente):
    - Antes do envio, valida se o cliente está integrado chamando setProtheusClienteIntegrado(f2_loja-f2_cliente).
    - Se o retorno não for true, o processamento do item é suspenso com:
        - suspensaoTipo = 'ProtheusCliente'
        - suspensaoChave = f2_loja-f2_cliente
        - situacao = 3 (suspenso por dependência)

    Normalizações e transformações numéricas pré-envio:
    - Cabeçalho:
        - f2_frete, f2_seguro, f2_despesa → normalizados por setNumeric().
    - Itens (para cada item):
        - d2_quant, d2_prcven, d2_total, d2_baseicm, d2_picm, d2_valicm, D2_DESCONsetNumeric().
        - D2_XIBSBS, D2_XIBSAL, D2_XIBSVL, D2_XCBSBS, D2_XCBSAL, D2_XCBSVLsetNumeric().

    Envio ao Protheus:
    - Endpoint lógico: linx/nota_fiscal via setProtheus('linx/nota_fiscal', payload, 'POST', headers).
    - Header aplicado: tenantId no formato UF,filial (ex.: substr(f2_filial, 0, 2) + "," + f2_filial).

    Validação e classificação do retorno:
    - Se não houver resposta → erro: JSON: NÃO HOUVE RESPOSTA.
    - Se code não existir no retorno → erro: JSON: NÃO FOI POSSÍVEL DECODIFICAR A RESPOSTA.
    - Montagem da mensagem final:
        - base em message
        - complemento em detailedMessage (quando existir).
    - Regra de idempotência: se a mensagem contiver "numero de nota fiscal ja gravado", trata como sucesso ajustando code = 0 e Mensagem = "OK".
    - Situação final do item:
        - 2 se code <= 299
        - 4 se code > 299

    Ações pós-sucesso:
    - Em sucesso (situacao = 2): registra integração da nota via setProtheusNotaFiscalOmniIntegrado e dispara atualização de cancelamento via setProtheusDocumentoCancelamentoSaida, utilizando a chave:
        - F2_FILIAL-F2_DOC-F2_SERIE-F2_CLIENTE-F2_LOJA.

    Persistência do item de fila:
    - Ao final, atualiza o item com retorno, mensagem, dump de requisição (_CURL_DUMP), tempo e situação (2, 3 ou 4).

    Notificação de erros:
    - notificar() consulta em wosk_queue os itens com acao = 'ProtheusNotaFiscalMarketplacePontual' e situacao = 4, formata e envia a notificação via _getNotificarErros.


    2. DADOS NECESSÁRIOS PARA O ENDPOINT

    Não há endpoint (WebService) implementado neste arquivo. Para a Queue, os dados necessários são os itens persistidos na fila.

    Estrutura do item de fila (campos utilizados neste arquivo):
    - token: identificador do item para consumo.
    - acao: ProtheusNotaFiscalMarketplacePontual.
    - chave: F2_FILIAL-F2_DOC-F2_SERIE-F2_CLIENTE-F2_LOJA.
    - conteudo: registro completo (cabeçalho + itens) capturado pelo monitor.
    - data_adicionado: data/hora de captura gravada no enfileiramento.


    3. REESTRUTURAÇÃO DOS DADOS

    3.1 Recuperação do item de fila
    Momento: Início do run(token)
    - Lê item via get(token).

    3.2 Reset ao iniciar execução
    Momento: Antes do envio
    - Atualiza o item para status Enviando e situacao = 1.

    3.3 Normalização do payload
    Momento: Pré-envio
    - Aplica mapeamento de campos via $field, incluindo a estrutura de itens.

    3.4 Atualização do estado para EXECUTANDO
    Momento: Pré-requisição
    - Mantém situacao = 1 enquanto processa e envia; troca para 2, 3 ou 4 ao concluir.

    3.5 Paginação dos registros
    Momento: Não aplicável (processa 1 item por execução).

    3.6 Sanitização dos dados
    Momento: Pré-envio
    - Normaliza campos numéricos com setNumeric() (cabeçalho e itens).

    3.7 Atualização do filtro de posição
    Momento: Não aplicável (controle de posição é do Monitor).

    3.8 Envio / Integração
    Momento: Envio ao Protheus
    - Executa setProtheus('linx/nota_fiscal', payload, 'POST', headers) com tenantId derivado de f2_filial.

    3.9 Atualização incremental da posição
    Momento: Não aplicável (não há offset na Queue).

    3.10 Finalização
    Momento: Pós-resposta do Protheus / pós-validação de dependência
    - Persiste situação final (2, 3 ou 4) e retorno/mensagem no item da fila.

    3.11 Tratamento de erro
    Momento: catch(Exception) interno do processamento do item
    - Define situacao = 4 e persiste retorno com erro e mensagem correspondente (ou situacao = 3 quando a falha for dependência de cliente).


    4. PERSISTÊNCIA DOS DADOS (BANCO DE DADOS)

    4.1 Controle do monitor
    Momento: Não aplicável para esta classe (não grava wosk_monitor).

    4.2 Fila de integração
    Momento: Durante todo o ciclo do item (get/set).
    - Tabela persistida: {$this->bancoIntegrador}.wosk_queue.
    - Suspensões (dependências) são persistidas no próprio item via _set (campos de suspensão repassados pela chamada).
    - Logs internos de falha de persistência podem ser gravados em {$this->bancoIntegrador}.wosk_queue_log (biblioteca wosk_queue).


    5. RESULTADO DO PROCESSAMENTO

    Execução normal:
    - Item finalizado com situacao = 2, retorno do Protheus persistido e integração registrada.

    Execução suspensa (dependência):
    - Item finalizado com situacao = 3, indicando dependência de cliente não atendida (ProtheusCliente).

    Execução com erro:
    - Item finalizado com situacao = 4 e mensagem persistida para auditoria e notificação.


    6. OPERAÇÃO MANUAL – capturar()

    Não aplicável para esta classe (a operação manual está na classe Monitor).

    Fluxo do Processo

    Diagrama sem nome.jpg

    Critérios de Aceitação

    Processo Subprocesso Descrição Situação esperada