Saltar al contenido principal

Importação de Notas de Crédito de Compra — Devolução de Compra do SAP B1

📌 Descrição do Processo

A importação de notas de crédito de compra representa o fluxo de recebimento de devoluções de compra do SAP B1 para o WMS. O SAP B1 atua como origem dos rascunhos (Drafts) do tipo oPurchaseCreditNotes, enquanto o WMS consome esses documentos para criar pedidos de saída segregada do tipo devolução.

A integração garante que as notas de crédito de compra geradas no SAP B1 sejam automaticamente registradas no WMS como pedidos com operação SaidaSegregado e sub-operação Devolução, incluindo produtos, quantidades e lotes.

Importante

Este processo utiliza cursor temporal para busca incremental — apenas rascunhos criados ou alterados desde a última sincronização são processados. A integração realiza verificação de duplicidade via IntegrationTracking (campo ExternalId = DocEntry), evitando reprocessamento de documentos já integrados. Além disso, apenas documentos com pelo menos um produto cujo código inicie com prefixos válidos configurados nos parâmetros B1 são incluídos.


🔄 Fluxo de Importação

  1. Consulta de Rascunhos de Notas de Crédito de Compra no SAP B1

    • O WMS busca rascunhos (Drafts) do tipo oPurchaseCreditNotes com status bost_Open no SAP B1, filtrando por DocDate a partir do cursor temporal.
    • Para cada rascunho encontrado, os detalhes completos do documento são recuperados via /Drafts({docEntry}).
    • Documentos cujas linhas não contêm nenhum produto com prefixo válido são descartados.
    • Documentos já presentes no IntegrationTracking (com ExternalId = DocEntry e tipo PurchaseDevolutionImport) são filtrados para evitar duplicidade.
  2. Transformação dos Dados (Parse)

    • Os dados brutos do SAP B1 (B1PurchaseCreditNoteResponse) são convertidos para o modelo interno OrderImport via AutoMapper.
    • Cada nota de crédito de compra gera um pedido com Operation = SaidaSegregado e SubOperation = "Devolução".
    • Lotes (BatchNumbers) são mapeados para OrderItemVolumeLots; linhas sem lote recebem um lote padrão vazio.
    • O RelationalLogisticOperationId é obtido do parâmetro DefaultLogisticOperationCode da integração.
  3. Salvamento no WMS

    • Os pedidos são persistidos no WMS via RecordOrderService.
    • Registros de IntegrationTracking são salvos para cada pedido (sucesso ou falha), com tipo PurchaseDevolutionImport.
    • O cursor de sincronização é atualizado com o DocEntry e a data do último documento processado.

🖥️ APIs Envolvidas

  • SAP B1 → WMS (GET)
    • /Drafts → busca rascunhos de notas de crédito de compra (DocObjectCode = "oPurchaseCreditNotes", DocumentStatus = "bost_Open"), filtrados por DocDate >= cursor.LastTimestamp, com campos selecionados (DocEntry, DocNum, DocObjectCode, DocDate, DocTime).
    • /Drafts({docEntry}) → recupera os detalhes completos de cada rascunho, incluindo DocumentLines, BatchNumbers, TaxExtension, AddressExtension e DocumentReferences.

📦 Exemplo de Importação (Objeto Fictício)

Cenário:

  • Fornecedor: Distribuidora XYZ S.A. (F00320)
  • Rascunho no SAP B1: DocEntry 60450, DocNum 70550
  • Produto devolvido: MA-312 – Chapa de Aço 2mm (50 unidades, lote LT-2026-080)
  • Valor total: R$ 7.500,00

1. Nota de Crédito de Compra no SAP B1

{
"DocEntry": 60450,
"DocNum": 70550,
"DocDate": "2026-03-25",
"DocTime": "10:15:00",
"CardCode": "F00320",
"CardName": "Distribuidora XYZ S.A.",
"DocTotal": 7500.00,
"DocumentStatus": "bost_Open",
"SequenceSerial": 85,
"SequenceCode": 5,
"DocumentLines": [
{
"LineNum": 0,
"ItemCode": "MA-312",
"ItemDescription": "Chapa de Aço 2mm",
"Quantity": 50,
"InventoryQuantity": 50,
"UnitPrice": 150.00,
"TaxCode": "ICMS-002",
"CFOPCode": "5202",
"WarehouseCode": "WH02",
"UoMEntry": 1,
"BatchNumbers": [
{
"BatchNumber": "LT-2026-080",
"Quantity": 50,
"ExpiryDate": "2027-03-25",
"ManufacturingDate": "2026-01-10"
}
]
}
],
"TaxExtension": {
"Carrier": "TRANS-001"
}
}

2. Pedido Criado no WMS

  • Pedido de saída segregada criado com sub-operação Devolução.
  • RelatedOrderCode: "60450" (DocEntry do rascunho).
  • RelationalEntityId: "F00320" (código do fornecedor).
  • InvoiceNumber: "85" (SequenceSerial).
  • RelationalCarrierCode: "TRANS-001" (transportadora).
  • Item: MA-312 — 50 unidades, lote LT-2026-080, classificação LIBERADO, warehouse WH02.

3. Resultado

  • IntegrationTracking registrado com ExternalId = "60450", tipo PurchaseDevolutionImport.
  • Cursor atualizado: LastId = "60450", LastTimestamp = 2026-03-25 10:15:00.

✅ Regras de Negócio

  • Apenas rascunhos (Drafts) do tipo oPurchaseCreditNotes com status bost_Open são consultados.
  • A busca é incremental via cursor temporal — apenas documentos com DocDate >= LastTimestamp são retornados pelo SAP B1.
  • Documentos cujas linhas não contêm nenhum produto com prefixo válido são descartados. Os prefixos padrão são: MA, MP, PA, PI, UC, RV (configuráveis por integração).
  • Documentos já presentes no IntegrationTracking (campo ExternalId = DocEntry, tipo PurchaseDevolutionImport) são filtrados, evitando reprocessamento.
  • Cada nota de crédito de compra gera um pedido com operação SaidaSegregado e sub-operação Devolução.
  • O RelationalLogisticOperationId é obtido do parâmetro DefaultLogisticOperationCode da integração (padrão: "116").
  • A quantidade do item utiliza InventoryQuantity quando disponível; caso contrário, utiliza Quantity.
  • Lotes com BatchNumber preenchido geram OrderItemVolumeLot com dados de lote, validade e fabricação. Linhas sem lote geram um lote padrão vazio (DefaultEmptyLote).
  • Todos os lotes recebem classificação de finalidade LIBERADO tanto na origem quanto no destino.
  • O WarehouseCode da linha é propagado para as classificações de origem e destino dos lotes.
  • A transportadora (RelationalCarrierCode) é extraída de TaxExtension.Carrier, quando disponível.
  • Em caso de falha em pedidos individuais, o cursor é posicionado no último pedido com erro, garantindo retentativa na próxima execução.
  • Cada operação (sucesso ou falha) gera um registro de IntegrationTracking com tipo PurchaseDevolutionImport, ExternalId = DocEntry e RelatedId = código do pedido no WMS.

Resumo

Esse fluxo garante que as notas de crédito de compra do SAP B1 sejam automaticamente importadas no WMS como pedidos de saída segregada do tipo devolução, mantendo rastreabilidade de lotes, consistência fiscal e prevenção de duplicidade.


⚙️ Especificações Técnicas

Fluxo de execução

  • Query: Consulta rascunhos de notas de crédito de compra no SAP B1 via B1DraftsConnector, filtra por prefixo de produto e duplicidade via IntegrationTracking.
  • Parse: Converte os dados retornados do SAP B1 para OrderImport via AutoMapper, com mapeamento de lotes e parâmetros de integração.
  • Send: Salva os pedidos no WMS via RecordOrderService, registra trackings de integração e atualiza o cursor para a próxima execução.

Detalhamento das Etapas

Query

B1PurchaseCreditNotesIntegrator.Query()
└── B1PurchaseCreditNotesImportService.GetIntegratedPurchaseCreditNotesAsync()
├── ErpIntegrationsService.GetErpToIntegrateAsync(EDefIntegration.B1)
├── ErpIntegrationsService.GetErpIntegrationCursorAsync(erp, PurchaseDevolutionImport)
├── B1DraftsConnector.GetDraftsAsync(config, "oPurchaseCreditNotes", lastTimestamp)
├── B1DraftsConnector.GetDraftByKeyAsync<B1PurchaseCreditNoteResponse>(docEntry)
├── Filtro por prefixo de produto (ValidProductPrefixes)
└── OrderIntegrationService.VerifyOrderIntegrationTrackingAsync(docEntries, PurchaseDevolutionImport)
  • B1PurchaseCreditNotesIntegrator.Query(): Ponto de entrada — delega ao serviço de importação.
  • B1PurchaseCreditNotesImportService.GetIntegratedPurchaseCreditNotesAsync(): Para cada integração ERP B1 ativa:
    1. Obtém o cursor da última execução (LastId, LastTimestamp).
    2. Busca rascunhos abertos do tipo oPurchaseCreditNotes no SAP B1, filtrando por DocDate >= LastTimestamp.
    3. Recupera os detalhes completos de cada rascunho via /Drafts({docEntry}).
    4. Filtra documentos por prefixo de produto válido.
    5. Remove documentos já processados via consulta ao IntegrationTracking.
    6. Retorna List<B1PurchaseCreditByIntegrator>.

Parse

B1PurchaseCreditNotesIntegrator.Parse()
└── B1PurchaseCreditNotesImportService.ParsePurchaseCreditNotesToOrdersAsync()
├── ErpIntegration.GetParametersOrDefault(parametersProvider)
└── AutoMapper: B1PurchaseCreditNoteResponse → OrderImport
├── RelatedOrderCode = DocEntry.ToString()
├── Operation = SaidaSegregado
├── SubOperation = "Devolução"
├── RelationalLogisticOperationId = DefaultLogisticOperationCode
├── B1PurchaseCreditNoteLine → OrderItem
│ └── Quantity = InventoryQuantity ?? Quantity
└── B1PurchaseCreditNoteBatch → OrderItemVolumeLot
├── Com lote: BatchNumber, ExpiryDate, ManufacturingDate
└── Sem lote: DefaultEmptyLote com quantidade total
  • B1PurchaseCreditNotesIntegrator.Parse(): Delega toda a transformação ao serviço.
  • B1PurchaseCreditNotesImportService.ParsePurchaseCreditNotesToOrdersAsync(): Para cada grupo de integração, obtém os parâmetros B1 e executa o mapeamento via AutoMapper. O mapeamento define operação SaidaSegregado, sub-operação Devolução, e trata lotes com classificação LIBERADO. Retorna List<ParsedPurchaseCreditNotesByIntegration>.

Send

B1PurchaseCreditNotesIntegrator.Send()
└── B1PurchaseCreditNotesImportService.SavePurchaseCreditNotesToWmsAsync()
├── RecordOrderService.RecordOrder(orders)
│ └── PedidoRepository.ImportOrderAsync(order)
├── SaveIntegrationTrackings()
│ └── OrderIntegrationService.SaveOrderIntegrationTrackingsAsync()
│ └── IntegrationTrackingRepository.AddRangeAsync()
└── UpdateIntegrationCursor()
└── ErpIntegrationsService.UpdateErpIntegrationCursorAsync()
  • B1PurchaseCreditNotesIntegrator.Send(): Itera sobre cada grupo de integração, logando quantidade de pedidos a salvar.
  • RecordOrderService.RecordOrder(): Persiste cada pedido no banco do WMS via PedidoRepository.ImportOrderAsync(). Retorna List<OperationResult<OrderImport>> com resultado individual por pedido.
  • SaveIntegrationTrackings(): Cria registros de IntegrationTracking com tipo PurchaseDevolutionImport, ExternalId = DocEntry e RelatedId = código do pedido no WMS.
  • UpdateIntegrationCursor(): Atualiza o cursor com LastId e LastTimestamp do último documento processado. Se houve erros, o cursor aponta para o último documento com falha, garantindo retentativa na próxima execução.

Resumo do Funcionamento

  • Busca incremental: Utiliza cursor temporal (LastTimestamp) para buscar apenas rascunhos novos ou alterados desde a última execução, reduzindo chamadas à API do SAP B1.
  • Filtragem por prefixo de produto: Apenas documentos com pelo menos um item cujo ItemCode inicie com prefixo válido (MA, MP, PA, PI, UC, RV) são processados.
  • Prevenção de duplicidade: Documentos já importados são identificados via IntegrationTracking.ExternalId (DocEntry) e excluídos antes do processamento.
  • Mapeamento com parâmetros: A transformação via AutoMapper utiliza parâmetros da integração (DefaultLogisticOperationCode, ValidProductPrefixes) injetados no contexto do mapper.
  • Rastreabilidade de lotes: Informações de lote (número, quantidade, validade, fabricação) são preservadas do SAP B1 para o WMS com classificação LIBERADO.
  • Persistência individual: Cada pedido é salvo individualmente — falhas em um pedido não impedem o processamento dos demais.
  • Cursor resiliente a falhas: Em caso de erro, o cursor é posicionado no último documento com falha, garantindo que a próxima execução retente a partir desse ponto.
  • Tratamento de erros: Cada operação gera um registro de IntegrationTracking com tipo PurchaseDevolutionImport, registrando sucesso ou falha com request e response serializados.