Especificação · Estrutural

Local de Entrega

Quem paga tem resposta no centro de custo; quem assina e quem recebe a nota, na spec de Empresa. Falta para onde o caminhão vai — e no Brasil essa não é uma pergunta de logística. A UF em que a mercadoria fisicamente entra decide alíquota de ICMS, DIFAL e substituição tributária, e a NF-e tem um grupo próprio para isso desde a NT 2018.005. Esta spec fecha a última entidade estrutural antes da espinha transacional: DeliveryLocation pendura no estabelecimento que recebe fiscalmente, tem endereço próprio quando precisa, e recusa em silêncio nenhuma operação interestadual.

depende de Establishment · CostCenter desbloqueia Requisition · PurchaseOrder · Receipt · Invoice 1 agregado · 1 value object · 3 ganchos declarados v1.2 · 08/09/2026

Ponto de partida

Oito decisões

Decisão 1 · Hierarquia

São dois conceitos e um deles já existe. Ship-to é o CNPJ que responde pela operação — é o Establishment, com IE, icmsTaxpayerStatus, Suframa e código IBGE. Deliver-to é o destino: doca, almoxarifado, andar, obra. Só o segundo nasce aqui. establishmentId é obrigatório e imutável — um ponto de entrega não muda de destinatário fiscal, isso seria outro ponto de entrega.

Decisão 2 · Endereço

Endereço próprio é opcional; ausente, herda o do estabelecimento. É o que faz um conceito só cobrir os quatro casos reais: doca e setor não têm endereço (herdam), CD alugado e canteiro de obra têm. Sem essa opcionalidade seriam duas entidades — uma de rótulo interno e outra de endereço — e toda consulta teria que olhar nas duas.

Decisão 3 · Fiscal

UF diferente da do estabelecimento exige motivo nomeado. Entregar em outro estado mantendo o destinatário original não cria tratamento interestadual — cria autuação. O modelo não impede o caso legítimo e não deixa o ilegítimo passar calado: interstateReason obrigatório, com os motivos que a legislação reconhece, e 422 sem ele.

Decisão 4 · Terceiro

CNPJ próprio no ponto de entrega só quando é de terceiro. Armazém geral, industrializador, entrega por conta e ordem. CNPJ nosso é Establishment, sempre — cadastrar filial como ponto de entrega é onde IE, Suframa e situação cadastral somem, e é exatamente o erro que a spec de Empresa já nomeia.

Decisão 5 · Eventual

Endereço eventual existe, mas nunca vira linha de catálogo. Vive só no snapshot do documento, exige permissão própria e obedece à mesma regra interestadual. E o catálogo se defende sozinho: a tela de administração lista os endereços eventuais repetidos com a contagem de uso, para virarem cadastro por um clique.

Decisão 6 · Documento

Cabeçalho define o padrão, linha sobrescreve — e o destinatário é um só. Todas as linhas de um documento entregam em locais do mesmo establishmentId do documento. Destinatário diferente é outro documento, não outra linha. É a regra da Oracle, e é a que evita nota impossível de emitir.

Decisão 7 · Obra

Obra é nó de centro de custo; aqui mora só o endereço dela. O CostCenter já ganhou vigência própria para obra e projeto. Modelar obra de novo aqui daria duas verdades sobre a mesma coisa. O vínculo é um defaultCostCenterId opcional que sugere o rateio — e nunca o contrário: centro de custo não ganha endereço.

Decisão 8 · Snapshot

A linha congela endereço, UF e motivo; a chave estrangeira é só rastro. Regra 1 do mapa de domínio, sem exceção. Renomear a obra, corrigir o CEP ou encerrar o ponto de entrega não pode reescrever o que a nota de seis meses atrás dizia — e a UF congelada é o que torna a conferência fiscal reproduzível.

Fundamento

Por que local de entrega é dimensão fiscal, e não campo de logística

A NF-e separa quem responde de onde chega — e o segundo grupo não transfere jurisdição

O leiaute tem o grupo dest, que identifica o destinatário da operação, e o grupo G · entrega, que identifica o local de entrega quando ele difere. Desde a NT 2018.005 esse grupo carrega CNPJ ou CPF, razão social do recebedor, endereço completo, município, UF, CEP, país, telefone, e-mail e inscrição estadual — e ganhou rejeições próprias para código de país e IE inválidos. É um grupo rico justamente porque a Receita quer o dado, não porque ele seja decorativo.

O que ele não faz é mudar de quem é a operação. Quem decide alíquota é o destinatário jurídico, o CNPJ que consta como dest.

E o critério de operação interna ou interestadual é a circulação física

As Respostas à Consulta da SEFAZ/SP são consistentes: o que define se a operação é interna ou interestadual é o fluxo físico efetivo da mercadoria, não o endereço cadastral do destinatário. A nota deve ser emitida para o adquirente com o endereço onde a entrega vai ocorrer, e o Grupo G preenchido quando o local difere do cadastro.

As duas coisas juntas produzem a única regra que este documento precisa impor

Entregar em outra UF mantendo o destinatário original não produz tratamento interestadual correto — produz divergência entre a alíquota aplicada e o destino real, que é o padrão que o fisco procura. O caminho certo é um dos três: o CNPJ que recebe passa a ser o destinatário; a operação usa uma triangulação que a legislação nomeia; ou a entrega acontece na mesma UF.

A construção civil tem uma dessas triangulações escrita: o RICMS/SP (Anexo XI, art. 4º, §3º) admite a compra com entrega direta no canteiro, sem passar pelo estabelecimento principal. É legislação estadual e varia por UF — o Nexio registra o motivo declarado e a UF efetiva; quem responde pela adequação é a assessoria fiscal do cliente.

O que muda de preço quando a UF muda

Alíquota interestadual de ICMS, DIFAL de destino, FCP e os convênios de substituição tributária — todos dependem da UF de destino, e todos entram no preço que o fornecedor cota. Um sistema de compras que trata destino como texto livre não consegue nem comparar duas propostas de UFs diferentes, nem conferir a nota contra o pedido. É por isso que stateCode é campo derivado do código IBGE e congelado na linha, exatamente como já é no Establishment.

O que esta spec deliberadamente não é. Não é motor de cálculo fiscal. O Nexio não apura ICMS, não resolve DIFAL e não decide CFOP. O que ele faz é garantir que a dimensão exista, seja obrigatória onde importa, esteja congelada no documento e chegue íntegra a quem calcula — que é o ERP fiscal. Registrar com precisão o fato é o escopo; tributá-lo não é.

Modelo

Mapa de entidades

DeliveryLocation aggregate root · Nexio O ponto de entrega. Pendura obrigatoriamente num Establishment, tem endereço próprio opcional, vigência, contato, janela de recebimento e instruções de acesso.
DeliveryAddressSnapshot value object · na linha O que o documento congela: endereço inteiro, stateCode, destinatário fiscal, CNPJ do recebedor e o motivo interestadual. Não é tabela própria — são colunas da linha.
Establishment outro documento · o ship-to Quem recebe fiscalmente. Já tem CNPJ de 14, IE, icmsTaxpayerStatus, Suframa, endereço fiscal e allowsReceiving. Nada é remodelado aqui.
CostCenter eixo irmão · sugestão Obra e projeto vivem lá, com vigência própria. Aqui só existe defaultCostCenterId, que sugere o rateio quando a entrega é naquele ponto.
ItemSupplier consome · preço por destino O gancho shipToLocationId vira shipToStateCode. Preço e prazo variam por UF, não por doca — e a UF já viaja congelada na linha, então o cadastro de fornecimento não precisa conhecer o ponto. Preço por sítio específico é do Contract.
Depósito · estoque fora de escopo O storage location do SAP e o depósito da Coupa. Ponto de entrega responde onde chega; depósito responde onde fica. Gancho previsto, nada implementado.

Convenção de nomes. O documento é escrito em português e todo identificador é em inglês — entidade, atributo, valor de enum, rota, permissão e código de erro. A exceção são os dados de negócio brasileiros, que ficam como são no mundo real: cnpj, stateRegistration, cityIbgeCode, suframaCode.

Uma tabela só: admin.delivery_locations. Índices: único parcial em (tenantId, companyId, code) filtrando isDeleted = false; um em (tenantId, establishmentId, isActive) para o lookup; e um em (tenantId, stateCode), que é o que a cascata de preço do ItemSupplier consulta.

Domínio

Campos · DeliveryLocation

Legenda: obrig sempre · cond conforme a operação · opc opcional · gerado calculado pelo sistema ou pelo banco.

Identificação

CampoTipoRegra
idGuidgeradoAtribuído pelo agregado, não pelo banco.
tenantIdGuidgeradoDo token, nunca aceito do cliente.
establishmentIdGuidobrigQuem recebe fiscalmente. Imutável — mudar de destinatário é criar outro ponto de entrega, porque todo documento já emitido congelou este valor. O estabelecimento precisa ter allowsReceiving = true.
companyIdGuidgeradoDerivado do estabelecimento e denormalizado. Existe para o escopo por empresa caber no filtro de linha sem join — mesmo padrão do Establishment.
codestring(20)obrigÚnico por empresa, imutável, normalizado em maiúsculas. CD-REC, OBRA-01, DOCA-3. Por empresa e não por estabelecimento porque é assim que a pessoa fala dele.
namestring(160)obrigComo o lugar é chamado. É o que aparece no seletor, sob o nome do estabelecimento.
typeenumobrigOwnSite · Warehouse · ConstructionSite · ThirdParty. Não é decorativo: ThirdParty é o único tipo que libera recipientCnpj, e ConstructionSite é o único que pré-seleciona o motivo interestadual.
externalCodestring(40)opcO código do local no ERP. Único por (tenant, empresa) quando preenchido.

Endereço · ausente, herda o do estabelecimento

CampoTipoRegra
hasOwnAddressboolgeradoVerdadeiro quando zipCode está preenchido. Existe como campo derivado para a consulta não testar seis colunas — e para a tela dizer "herda o endereço da filial" em vez de mostrar campos vazios.
zipCodevarchar(8)condSem máscara. Preenchido, obriga o bloco inteiro; vazio, o bloco inteiro tem que estar vazio. Nunca endereço pela metade422.
street · number · complement · districtstringcondLogradouro e bairro obrigatórios com o bloco ativo; número aceita S/N, que é o caso normal de canteiro de obra.
cityIbgeCodevarchar(7)condCódigo do município, não o nome. É o que a NF-e carrega no Grupo G e o que resolve homônimo entre estados. O nome é derivado dele, nunca digitado livre.
stateCodechar(2)geradoDerivado do código IBGE quando há endereço próprio; copiado do estabelecimento quando não há. É a dimensão que muda o ICMS — por isso nunca é digitada em separado e nunca fica nula.
countryCodechar(2)opcISO 3166-1, padrão BR. Reservado; entrega fora do Brasil está fora de escopo.

Fiscal

CampoTipoRegra
interstateReasonenum?condObrigatório quando stateCode difere do stateCode do estabelecimento, e recusado quando não difere. ConstructionSite · GeneralWarehouse · ThirdPartyProcessing · DirectToCustomer · Other. Ver § A regra interestadual.
interstateReasonNotestring(400)?condObrigatória quando o motivo é Other. É o campo que a auditoria lê primeiro, e é o único texto livre desta entidade — de propósito.
recipientCnpjvarchar(14)?condSó com type = ThirdParty. Recusado quando o CNPJ é de um Establishment do próprio tenant — a mensagem nomeia o estabelecimento e manda usar ele. VARCHAR, nunca numérico: CNPJ alfanumérico está em produção desde 31/07/2026.
recipientNamestring(160)?condRazão social do recebedor. Obrigatória com recipientCnpj. Vai para o xNome do Grupo G da NF-e.
recipientStateRegistrationvarchar(20)?opcIE do recebedor terceiro. A NT 2018.005 criou rejeição própria para IE inválida no grupo de entrega — o campo existe para que ela nunca seja disparada.

Operação · o que faz valer a pena ser entidade

CampoTipoRegra
contactName · contactPhone · contactEmailstringopcQuem recebe no local. É o attention line da Coupa, e é o nome que o motorista procura no portão.
receivingHoursstring(120)?opcJanela de recebimento como texto exibível — Seg a Sex, 08:00–11:30 e 13:00–16:30. Texto e não agenda: agendamento de doca é outro produto, e uma agenda que ninguém mantém é pior que uma frase certa.
deliveryInstructionstext?opcAcesso, portaria, restrição de veículo, exigência de EPI. Sai impressa no PDF do pedido — é a razão pela qual o fornecedor acerta a entrega na primeira tentativa.
requiresSchedulingboolopcPadrão false. Verdadeiro, o pedido sai com aviso de agendamento obrigatório e o recebimento sem agendamento gera divergência, não bloqueio.
defaultCostCenterIdGuid?opcSugere o rateio quando a entrega é aqui. Sugestão, nunca imposição — o rateio continua sendo da linha. Ver § Obra e centro de custo.

Vigência e estado

CampoTipoRegra
validFromdateobrigPadrão hoje. Mesmo padrão de CostCenterAssignment.
validTodate?opcObra acaba. Nulo é o caso comum. Vencido, o ponto some do seletor sem que nenhum documento antigo mude de significado.
isActiveboolgeradoSó por /activate e /deactivate; PUT nunca muda. Desativar com documento em aberto que entrega ali é 409 com a lista do que impede — mesma decisão da unidade de medida.
Não existe allowsDelivery. O propósito é a própria existência da entidade — diferente do SupplierAddress, onde um mesmo endereço acumula flags de pedido, cobrança e RFQ. Aqui o registro só existe para receber; um lugar que deixou de receber se desativa.

Invariante fiscal

A regra interestadual

Uma comparação, disparada em três lugares: ao salvar o ponto de entrega, ao usá-lo num documento e ao aceitar um endereço eventual. deliveryStateCode ≠ establishment.stateCode exige motivo declarado.

MotivoO casoO que o Nexio faz
ConstructionSiteCanteiro de obra em outro estado. O RICMS/SP (Anexo XI, art. 4º, §3º) admite a compra com entrega direta no canteiro, sem passar pelo estabelecimento principal — e regra equivalente existe na maioria das UFs, com redação própria.Pré-selecionado quando type = ConstructionSite. Exige defaultCostCenterId preenchido, porque obra sem centro de custo não tem como ser conferida depois.
GeneralWarehouseArmazém geral ou operador logístico terceirizado, com documentação própria de depósito.Exige type = ThirdParty e recipientCnpj. O armazém é pessoa jurídica distinta e precisa aparecer no Grupo G.
ThirdPartyProcessingRemessa por conta e ordem para industrialização — a mercadoria vai direto ao industrializador.Idem. O CFOP da operação é do ERP fiscal; o Nexio registra o fato e o CNPJ.
DirectToCustomerEntrega direta ao cliente final (drop ship). Existe em revenda e em contrato de fornecimento com montagem.Marca a linha para o relatório de operação triangular. É o único motivo que aceita destinatário no endereço eventual, com CPF ou CNPJ no snapshot (RN-DL-13); no cadastro, como os dois de cima, exige type = ThirdParty e CNPJ.
OtherO que a lista não cobre.interstateReasonNote obrigatória. É o caso que a auditoria vai ler um por um, e é por isso que ele custa uma frase escrita.
O enum é fechado de propósito. Motivo como texto livre vira "conforme combinado" em 80% das linhas no terceiro mês, e aí a dimensão existe sem informar nada — que é exatamente o argumento do ReasonCode no mapa de domínio.

Por que a checagem é de UF e não de município

Município diferente na mesma UF não muda ICMS e não precisa de justificativa — muda só o Grupo G da nota, que é registro, não escolha. ISS é outra história e está fora desta versão: em serviço, o município de prestação decide a retenção, e a dimensão relevante não é para onde a mercadoria vai. O gancho está declarado no fora de escopo; quando o módulo de serviços existir, a checagem ganha um irmão municipal.

O Nexio avisa, não julga

O sistema não diz que a operação é legal — ele diz que ela é interestadual e obriga alguém a declarar sob qual hipótese. A adequação é da assessoria fiscal do cliente, e a legislação é estadual. O que o produto garante é que a informação existe, é estruturada e chega ao ERP fiscal junto com o documento, em vez de ser descoberta na conferência da nota.

A saída óbvia continua disponível — e é a certa

Se o grupo tem CNPJ no estado de destino, o caminho correto é esse CNPJ ser o destinatário: cadastra-se o Establishment, e o ponto de entrega pendura nele. Aí stateCode coincide, nenhum motivo é exigido e a operação é uma venda interestadual comum entre fornecedor e filial. A mensagem de erro diz isso — não é só uma recusa, é uma sugestão nomeada.

A válvula de escape

Endereço eventual

Toda operação real tem a entrega que não cabe no cadastro: o evento, a feira, a casa do executivo que recebe o notebook, a obra de dois meses que não vale um registro. O SAP tem one-time delivery address exatamente para isso. Negar o caso não o elimina — empurra a informação para o campo de observação, onde ela não é dimensão de nada.

Existe, e vive só no documento

O endereço eventual é preenchido no documento e gravado no snapshot da linha com isOneTimeDelivery = true e deliveryLocationId nulo. Nenhuma linha entra em delivery_locations. Não tem código, não aparece em lookup, não pode ser reutilizado por busca e não polui o catálogo — que é a única coisa que fazia valer a pena proibi-lo.

Não é exceção às regras, é exceção ao cadastro

Continua exigindo establishmentId — alguém tem que ser o destinatário, e endereço eventual não cria CNPJ. Continua derivando stateCode do código IBGE. E continua obedecendo à regra interestadual: endereço eventual em outra UF exige interstateReason no documento, com a mesma lista fechada. O que ele dispensa é o cadastro, não o rigor.

Permissão própria, porque é uma decisão e não uma conveniência

use:delivery-location-one-time é separada de read:delivery-location. Um cliente que quer disciplina de catálogo simplesmente não concede — e a funcionalidade desaparece da tela, sem flag de configuração e sem código morto. É a mesma mecânica de permissão que o resto do produto já usa para separar quem lê de quem decide.

O catálogo se defende sozinho

O padrão de falha do endereço eventual é conhecido: ele vira o caminho normal, e em um ano o cadastro tem três pontos de entrega e o histórico tem quatrocentos endereços digitados. A defesa é medir. GET /delivery-locations/one-time-usage agrupa os snapshots eventuais dos últimos N dias por CEP e número, com a contagem de uso e os documentos — e a tela oferece "cadastrar como ponto de entrega" num clique, já preenchido. Endereço eventual usado cinco vezes não é eventual; é um cadastro que ninguém fez.

O que o eventual quase nunca faz. Não aceita destinatário de terceiro — entrega a terceiro é decisão de cadastro, com CNPJ conferido, e não texto digitado às pressas na tela do pedido. A exceção, aberta em 08/09/2026, é uma só: interstateReason = DirectToCustomer (RN-DL-13). Não aceita defaultCostCenterId, porque o rateio da linha já está lá. E não é editável depois de o documento sair do rascunho: a partir daí é snapshot, e snapshot não se corrige — corrige-se o documento, que gera versão nova.

Consumo

Cabeçalho, linha e o que a linha congela

O cabeçalho define o padrão; a linha sobrescreve

Requisição, pedido e recebimento carregam deliveryLocationId no cabeçalho, e cada linha pode apontar para outro ponto. É consistente com o rateio, que já é por linha desde o Centro de Custo — uma requisição de escritório com três itens para a matriz e um para a obra é o caso comum, não a exceção.

Trocar no cabeçalho pergunta o que fazer com as linhas

A documentação do SAP tem um aviso que vale copiar inteiro: editar só o cabeçalho ou só o item cria descasamento silencioso — "edite tudo ou não edite nada". Aqui a propagação é explícita: mudar o ponto do cabeçalho pergunta "aplicar às N linhas que ainda usam o local anterior?", e as linhas que já foram alteradas à mão nunca são sobrescritas em silêncio.

Um documento, um destinatário

Todas as linhas entregam em pontos do mesmo establishmentId do documento. É a regra da Oracle — o deliver-to só é válido quando o ship-to dele bate com o do documento — e a razão é que uma nota tem um destinatário só. Precisa de dois CNPJs? São dois pedidos. DELIVERY_LOCATION_ESTABLISHMENT_MISMATCH_UNPROCESSABLE, 422, nomeando a linha.

O que a linha congela

Pela Regra 1 do mapa de domínio, sem exceção: a chave estrangeira é rastro, o snapshot é a verdade. Renomear a obra, corrigir o CEP, encerrar o ponto ou desativá-lo não pode reescrever o que o pedido de seis meses atrás dizia.

Campo na linhaTipoRegra
deliveryLocationIdGuid?Rastro. Nulo quando a entrega é eventual. Nunca usado para ler o endereço na exibição do documento.
deliveryEstablishmentIdGuidO destinatário fiscal, congelado. Igual ao do cabeçalho, sempre.
deliveryAddresscolunasCEP, logradouro, número, complemento, bairro e cityIbgeCode. Colunas, não jsonb: a UF entra em índice e em relatório, e jsonb aqui é conveniência de escrita paga na leitura.
deliveryStateCodechar(2)A dimensão fiscal congelada. É por ela que a conferência a três compara pedido, recebimento e nota, e é ela que o ERP fiscal consome.
deliveryRecipientTaxId · deliveryRecipientNamevarchar(14)? · string(160)?Grupo G da NF-e, quando há terceiro. Congelados junto. Renomeado em 08/09/2026: chamava-se deliveryRecipientCnpj, e o nome era estreito demais — o drop ship a consumidor final põe um CPF no Grupo G. varchar(14) cobre os dois; quem valida o dígito olha o comprimento. O campo do cadastro continua recipientCnpj e continua só CNPJ (RN-DL-06): é no snapshot que a pessoa física cabe, porque ali ela é um fato daquele documento, não uma linha permanente de cadastro.
deliveryInterstateReason · Noteenum? · string(400)?Congelados. Mudar a política do cadastro depois não reescreve a justificativa que valeu naquele documento.
isOneTimeDeliveryboolVerdadeiro só no endereço eventual. É o que alimenta /one-time-usage.
Sete colunas por linha parece caro e não é: são as mesmas sete que o Grupo G da NF-e exige na conferência, e reconstruí-las por join depois de o cadastro ter mudado é impossível — que é a definição de snapshot no resto deste produto.

Fronteira interna

Obra e centro de custo — o caso que obriga o desenho

Obra já existe, e existe do outro lado

O CostCenter ganhou vigência própria com a justificativa escrita: "obra e projeto". Obra é nó da árvore de quem paga, com responsável, alçada, orçamento e data de encerramento. Modelar obra aqui de novo daria duas verdades sobre a mesma coisa — e a segunda sempre fica desatualizada, porque é a que ninguém abre.

São dimensões diferentes de propósito, e a assimetria é o desenho

Uma obra pode receber material em dois pontos (o canteiro e o depósito de apoio) e um ponto de entrega pode servir a várias obras (o CD que abastece três frentes). Não é um para um, e por isso não é um campo. O vínculo é DeliveryLocation.defaultCostCenterId, opcional e unidirecional: o ponto de entrega sugere o centro de custo, e o centro de custo nunca ganha endereço.

Sugerir é preencher o rateio, não travá-lo

Ao escolher um ponto de entrega com defaultCostCenterId, a linha nasce com aquele centro de custo em 100% — e o requisitante pode trocar ou ratear. É a mesma mecânica da conta contábil sugerida por Item.defaultGlAccountId e depois por CategoryNode: o sistema propõe, a pessoa responde, o documento congela.

As duas vigências são independentes, e a divergência é avisada

A obra encerra no centro de custo e o ponto de entrega fica ativo, ou o contrário. Nenhum dos dois cascateia para o outro — cascata entre agregados diferentes é como se cria exclusão que ninguém pediu. O que existe é aviso: desativar um nó de centro de custo que é defaultCostCenterId de pontos ativos lista quais são, e segue.

Canteiro em outra UF junta as duas regras. type = ConstructionSite com stateCode diferente exige interstateReason = ConstructionSite e defaultCostCenterId preenchido. A segunda exigência não é fiscal, é de conferência: entrega em canteiro é o caso em que material some entre a nota e a obra, e sem o nó de custo amarrado desde o cadastro ninguém reconstrói para onde foi.

Transversal

Escopo e visibilidade

O escopo vem de graça, e é essa a vantagem de establishmentId obrigatório

companyId é derivado do estabelecimento e denormalizado na linha. O conjunto de empresas resolvido a cada requisição por UserCompanyScope é o filtro — não há segunda regra de visibilidade, não há tabela nova e não há nada para lembrar de validar. Ponto de entrega de empresa fora do escopo do usuário responde 404, nunca 403, pela mesma decisão já tomada em centro de custo e em empresa.

O seletor mostra o que dá para usar, e some quando não há escolha

GET /delivery-locations/lookup?establishmentId=… devolve os pontos vigentes e ativos daquele estabelecimento, agrupados. Um item na resposta e nenhuma permissão de eventual: o campo não aparece na tela, e o único ponto é aplicado em silêncio — mesma decisão do seletor de estabelecimento. Zero itens e nenhuma permissão de eventual é erro de cadastro, e a tela diz isso com o link para o cadastro em vez de mostrar um combo vazio.

CD compartilhado entre empresas do grupo são N registros, e está certo

O mesmo galpão que recebe para três empresas do grupo vira três DeliveryLocation, um por CNPJ destinatário. Parece duplicação e não é: fiscalmente são três operações diferentes, com três notas, três destinatários e possivelmente três tratamentos de ICMS. Um registro com N donos precisaria escolher um destinatário na hora de emitir — que é a decisão que este campo existe para não deixar implícita.

Integração

Relação com os demais domínios

DomínioMudançaO quê
Empresa e EstabelecimentonenhumaÉ a dependência, e ela já está pronta. allowsReceiving e allowsPurchasing já nasceram como eixos separados, e stateCode já é derivado do IBGE. Nenhum campo novo.
Centro de CustonenhumaA vigência de obra já existe no Centro de Custo. O vínculo é de mão única e mora aqui, em defaultCostCenterId. O nó não ganha endereço.
Cadastro de ItemacrescentaO gancho shipToLocationId vira shipToStateCode e entra na chave do ItemSupplier. O que muda preço é frete e tributação, que são por UF — dois pontos na mesma cidade não têm preço diferente, e chavear pelo ponto faria o catálogo crescer sem teto. A chave de busca é o deliveryStateCode já congelado na linha, então resolver preço não consulta o cadastro do ponto. Cascata: UF exata > linha sem destino. Preço por sítio específico — canteiro remoto, ilha — é negociado, e por isso é do Contract, que já é o topo da precedência.
Fluxo de AprovaçãoacrescentaGanha o critério UF de entrega em lista, irmão dos critérios de empresa e estabelecimento. Motivo real: entrega interestadual muda o custo e várias empresas querem que ela passe por quem responde pelo fiscal. Nenhuma entidade nova.
OrçamentonenhumaVerba é por empresa, centro de custo, conta e período. Local de entrega não é dimensão orçamentária e não deve virar uma — a linha já leva o centro de custo que o ponto sugeriu.
Moeda e CâmbionenhumaSem interseção. A moeda é do documento e do fornecedor.
FornecedornenhumaSupplierAddress continua sendo o endereço dele, com as flags de propósito. Este documento modela o endereço nosso. A simetria termina aí de propósito: o fornecedor tem um endereço com vários papéis; nós temos vários pontos com um papel só.
Requisição · Pedido · Recebimento · Notaa especificarNascem já com as sete colunas de snapshot, deliveryLocationId no cabeçalho e por linha, e a validação de destinatário único. É o motivo de esta spec vir antes delas.

Interface

Telas

Admin · lista

Pontos de entrega agrupados por empresa e estabelecimento, com UF, tipo, vigência e estado. Filtro por UF é o primeiro da barra, não o último — é a coluna que a pessoa do fiscal procura. Ponto interestadual leva marca visual com o motivo no tooltip.

Admin · cadastro

Estabelecimento primeiro, tudo depois — a UF dele é o que decide se o bloco de motivo aparece. O endereço começa recolhido com "herda o endereço da filial" escrito e um botão para abrir; o CEP preenche logradouro, bairro e município, e o município traz a UF, sempre bloqueada.

Admin · endereços eventuais

A tela que impede o catálogo de apodrecer. Lista os snapshots eventuais dos últimos 90 dias agrupados por CEP e número, ordenados por contagem de uso, com os documentos ao lado e o botão "cadastrar como ponto de entrega" já preenchido.

Documento · seletor

Um campo no cabeçalho, agrupado por estabelecimento, com o padrão do usuário pré-selecionado. Um item só e sem permissão de eventual: o campo não aparece. Escolha interestadual abre o motivo ali mesmo, com a hipótese pré-selecionada quando o tipo do ponto a determina.

Documento · linha

Coluna de entrega visível só quando a linha diverge do cabeçalho — caso contrário é ruído em cima do caso comum. Trocar o cabeçalho pergunta antes de propagar, e nomeia quantas linhas serão afetadas e quantas ficaram como estão.

Pedido · impressão

O PDF traz o bloco de entrega inteiro: nome, endereço, contato, janela de recebimento e as instruções de acesso. É a única tela desta spec que o fornecedor vê, e é onde ela paga o próprio custo.

API

Endpoints

RotaPermissãoDevolveErros
GET /delivery-locationsread:delivery-locationPagedResult<DeliveryLocationDto>, filtrável por empresa, estabelecimento, tipo, UF e vigência400
GET /delivery-locations/{id}read:delivery-locationDeliveryLocationDto com o endereço efetivo — o próprio ou o herdado, resolvido no servidor404
GET /delivery-locations/lookupread:delivery-locationO seletor. Só vigentes e ativos do estabelecimento pedido, agrupados, com stateCode para a tela decidir se pede motivo400
POST /delivery-locationsmanage:delivery-locationDeliveryLocationDto400 · 404 · 409 · 422
PUT /delivery-locations/{id}manage:delivery-locationDeliveryLocationDto. establishmentId e code são recusados quando divergem404 · 409 · 422
PATCH /delivery-locations/{id}/activatemanage:delivery-locationEstado só por rota própria, nunca por PUT404 · 422
PATCH /delivery-locations/{id}/deactivatemanage:delivery-location404 · 409
GET /delivery-locations/{id}/blocking-documentsread:delivery-locationO que impede desativar, por tipo e com contagem. A tela pergunta antes de agir, em vez de descobrir no 409404
DELETE /delivery-locations/{id}manage:delivery-locationExiste só para cadastro errado no mesmo dia. Com documento, é desativação404 · 409
GET /delivery-locations/one-time-usagemanage:delivery-locationEndereços eventuais agrupados por CEP e número, com contagem e documentos. Janela padrão de 90 dias400
POST /delivery-locations/from-one-timemanage:delivery-locationCria o cadastro a partir de um snapshot eventual. Não reescreve os documentos passados — eles continuam com o que congelaram400 · 409 · 422
POST /delivery-locations:importmanage:delivery-locationLote, tudo ou nada, com ?dryRun=true obrigatório antes — a mesma mecânica do centro de custo. Cliente com quarenta filiais e canteiros não digita um por um400 · 422
O endereço efetivo é sempre resolvido no servidor. Nenhum cliente reimplementa "se hasOwnAddress então… senão…" — foi assim que o produto acabou com duas regras de herança de conta contábil em telas diferentes, e não se repete aqui.

Contrato

Contrato de erros

O status HTTP é derivado do sufixo do código, nunca da mensagem: o mapeador do Core reconhece nove sufixos — _NOT_FOUND → 404 · _ALREADY_EXISTS, _ALREADY_ASSIGNED e _CONFLICT → 409 · _FORBIDDEN, _ACCESS_DENIED e _BLOCKED → 403 · _UNAUTHORIZED → 401 · _UNPROCESSABLE → 422 · sem sufixo → 400. _UNAVAILABLE → 503 seria o décimo: é extensão pedida ao Core pelo épico do GrydFiles, ainda não vigente — conferido no código da plataforma em 08/09/2026.

CódigoHTTPQuando
DELIVERY_LOCATION_NOT_FOUND404Não existe neste tenant — ou não está no escopo do usuário. Os dois casos respondem igual, de propósito
DELIVERY_LOCATION_CODE_ALREADY_EXISTS409Código repetido dentro da mesma empresa. A mensagem carrega o código
DELIVERY_LOCATION_EXTERNAL_CODE_ALREADY_EXISTS409Código do ERP repetido na mesma empresa
DELIVERY_LOCATION_IN_USE_CONFLICT409Desativação ou exclusão com documento em aberto entregando ali. A mensagem traz a contagem por tipo de documento
DELIVERY_LOCATION_ESTABLISHMENT_IMMUTABLE_CONFLICT409Tentativa de trocar o destinatário fiscal. A mensagem manda criar outro ponto
DELIVERY_LOCATION_ESTABLISHMENT_NOT_RECEIVING_UNPROCESSABLE422Estabelecimento com allowsReceiving = false
DELIVERY_LOCATION_ADDRESS_INCOMPLETE_UNPROCESSABLE422Bloco de endereço pela metade. Ou tudo, ou nada
DELIVERY_LOCATION_INTERSTATE_REASON_REQUIRED_UNPROCESSABLE422UF do endereço difere da do estabelecimento e nenhum motivo foi declarado. A mensagem sugere o caminho alternativo: cadastrar um estabelecimento na UF de destino
DELIVERY_LOCATION_INTERSTATE_REASON_NOT_APPLICABLE_UNPROCESSABLE422Motivo informado com UF igual. Justificativa que não justifica nada é ruído em relatório de auditoria
DELIVERY_LOCATION_INTERSTATE_NOTE_REQUIRED_UNPROCESSABLE422Motivo Other sem interstateReasonNote
DELIVERY_LOCATION_RECIPIENT_NOT_ALLOWED_UNPROCESSABLE422recipientCnpj com type diferente de ThirdParty
DELIVERY_LOCATION_ONE_TIME_RECIPIENT_NOT_ALLOWED_UNPROCESSABLE422Novo. Destinatário no endereço eventual com interstateReason diferente de DirectToCustomer. A mensagem diz qual é o único motivo que o aceita (RN-DL-13)
DELIVERY_LOCATION_RECIPIENT_IS_OWN_ESTABLISHMENT_UNPROCESSABLE422O CNPJ do recebedor é de um estabelecimento do próprio tenant. A mensagem nomeia o estabelecimento e manda usá-lo
DELIVERY_LOCATION_CONSTRUCTION_COST_CENTER_REQUIRED_UNPROCESSABLE422Canteiro interestadual sem defaultCostCenterId
DELIVERY_LOCATION_COST_CENTER_UNPROCESSABLE422defaultCostCenterId de outra empresa, fora de vigência, ou nó que não aceita lançamento
DELIVERY_LOCATION_ESTABLISHMENT_MISMATCH_UNPROCESSABLE422Linha de documento entregando em ponto de outro estabelecimento. Nomeia a linha
DELIVERY_LOCATION_NOT_EFFECTIVE_UNPROCESSABLE422Ponto fora da vigência na data do documento, ou inativo
ONE_TIME_DELIVERY_NOT_PERMITTED_UNPROCESSABLE422Endereço eventual sem a permissão use:delivery-location-one-time
ONE_TIME_DELIVERY_RECIPIENT_NOT_ALLOWED_UNPROCESSABLE422CNPJ de recebedor num endereço eventual. Entrega a terceiro é decisão de cadastro
DELIVERY_LOCATION_CODE_REQUIRED · _TOO_LONG · _NOT_ALPHANUMERIC400Validações de código, herdadas do padrão do centro de custo
DELIVERY_LOCATION_NAME_REQUIRED · _TOO_LONG400Nome em branco ou acima de 160
DELIVERY_LOCATION_ZIP_CODE_INVALID · _CITY_IBGE_CODE_INVALID400CEP fora de oito dígitos; código IBGE que não existe na tabela de municípios

Autorização

Permissões

PermissãoAlcanceObservação
read:delivery-locationListar, ler e usar no documentoRecortada pelo escopo do usuário. Todo papel que emite documento precisa dela
manage:delivery-locationCriar, editar, ativar, desativar, importar e promover eventualAdministração de cadastro. Separada de read pelo mesmo motivo de sempre
use:delivery-location-one-timeDigitar endereço eventual no documentoSeparada de propósito. Não conceder é a forma de exigir disciplina de catálogo — sem parâmetro de configuração e sem código morto
Três permissões e nenhuma configuração de tenant. A política do cliente sobre endereço eventual é expressa em quem tem a permissão, e não numa chave em Settings que ninguém encontra depois.

Invariantes

Regras de negócio

RN-DL-01Todo ponto de entrega tem um destinatário fiscal

establishmentId é obrigatório e o estabelecimento precisa ter allowsReceiving = true. Não existe ponto de entrega solto no tenant: alguém sempre responde pela nota.

RN-DL-02O destinatário é imutável

establishmentId e code não mudam depois de criados. Todo documento emitido congelou o primeiro; o segundo é a identidade pela qual as pessoas falam do lugar. Mudança é registro novo.

RN-DL-03Endereço é bloco: tudo ou nada

CEP preenchido obriga logradouro, bairro e município. CEP vazio obriga o bloco inteiro vazio. Endereço pela metade não herda nem sobrescreve — só produz nota rejeitada.

RN-DL-04stateCode nunca é digitado e nunca é nulo

Derivado do cityIbgeCode quando há endereço próprio, copiado do estabelecimento quando não há. É a dimensão que muda o imposto — não pode divergir do município e não pode faltar.

RN-DL-05UF divergente exige motivo declarado

A invariante central desta spec. stateCode diferente do estabelecimento exige interstateReason da lista fechada; igual, recusa o motivo. Verificada no cadastro, no uso em documento e no endereço eventual — os três caminhos, sempre.

RN-DL-06CNPJ no ponto de entrega só quando é de terceiro

recipientCnpj exige type = ThirdParty, e é recusado quando o CNPJ pertence a um Establishment do próprio tenant. Filial cadastrada como endereço perde IE, Suframa e situação cadastral — e o sistema não deixa acontecer por engano.

RN-DL-07Canteiro interestadual exige centro de custo

type = ConstructionSite com UF divergente exige defaultCostCenterId. Não é regra fiscal, é de conferência: é o caso em que material some entre a nota e a obra.

RN-DL-08Um documento, um destinatário

Todas as linhas entregam em pontos do mesmo establishmentId do documento. Dois CNPJs destinatários são dois documentos, porque são duas notas.

RN-DL-09A linha congela; a chave estrangeira é rastro

Endereço, UF, destinatário, CNPJ do recebedor e motivo vão para colunas da linha na criação. A exibição do documento nunca lê o cadastro. Regra 1 do mapa de domínio, sem exceção.

RN-DL-10Propagação de cabeçalho para linha é explícita

Trocar o ponto do cabeçalho pergunta antes, informa quantas linhas serão afetadas e nunca sobrescreve linha alterada à mão.

RN-DL-11Endereço eventual não vira cadastro

Vive só no snapshot, com isOneTimeDelivery = true e deliveryLocationId nulo. Não tem código, não entra em lookup e não é reutilizável por busca. Virar cadastro é ato explícito, por /from-one-time.

RN-DL-13Destinatário no eventual existe para um caso só: drop ship a consumidor final

Nova em 08/09/2026. O snapshot eventual aceita deliveryRecipientTaxId e deliveryRecipientName se e somente se interstateReason = DirectToCustomer; em qualquer outro motivo é 422. Por que era preciso abrir: entrega direta ao cliente final é, por natureza, eventual — o comprador não volta a entregar naquele endereço —, e o único caminho eventual do produto recusava destinatário. O resultado era um valor de enum que não funcionava: DirectToCustomer só servia para pessoa jurídica já cadastrada como ponto de entrega, que é justamente o caso que ele não descreve. Por que a exceção para aqui: o consumidor final costuma ser pessoa física, e CPF em cadastro permanente é dado pessoal que o produto guardaria sem precisar. No snapshot ele é o que sempre foi — um fato congelado daquele documento, que a nota já vai carregar no Grupo G de qualquer forma. O cadastro não muda: ponto de entrega de terceiro continua exigindo type = ThirdParty e CNPJ (RN-DL-06). E o /one-time-usage continua contando: drop ship repetido para o mesmo destinatário é revenda com carteira, e aí vira cadastro.

RN-DL-12Endereço eventual obedece às mesmas regras fiscais

Exige estabelecimento, deriva stateCode do IBGE e cumpre a RN-DL-05. O que ele dispensa é o cadastro, não o rigor. E não aceita destinatário de terceiro, salvo o caso único da RN-DL-13.

RN-DL-13Promover eventual a cadastro não reescreve o passado

/from-one-time cria o registro daqui para a frente. Os documentos que usaram o endereço continuam com deliveryLocationId nulo e o snapshot que congelaram — porque naquele momento não havia cadastro, e o histórico registra o que aconteceu.

RN-DL-14Vigência não cascateia entre agregados

Encerrar o nó de centro de custo não encerra o ponto de entrega, e vice-versa. O que existe é aviso com a lista do que ficou pendurado. Cascata entre agregados diferentes é como se cria exclusão que ninguém pediu.

RN-DL-15Desativar com documento em aberto é recusado

409 com a contagem por tipo de documento. Documento fechado e histórico não impedem: continuam legíveis com o que congelaram, com marca visual de ponto inativo. Mesma decisão da unidade de medida.

RN-DL-16defaultCostCenterId sugere, nunca impõe

A linha nasce com aquele centro de custo em 100% e o requisitante pode trocar ou ratear. O sistema propõe, a pessoa responde, o documento congela — a mesma mecânica da conta contábil sugerida pelo item.

RN-DL-17O endereço efetivo é resolvido no servidor

Nenhum cliente reimplementa a herança. A API sempre devolve o endereço final e diz de onde ele veio, do mesmo jeito que a política de orçamento devolve de qual nó cada valor foi resolvido.

Aferição

Referência de mercado

NexioSAPCoupaOracle FusionNota
Separação ship-to × deliver-toWerk / Lagerort × endereço de entrega no itemShip-to Location × Deliver-to LocationA Oracle é a mais explícita, e a frase deles resume: "end users care about Deliver-To; suppliers care about Ship-To"
establishmentId obrigatório no pontoendereço herda do planto deliver-to site carrega o ship-to associadoA Oracle recusa a combinação quando o ship-to do local não bate com o do documento. É a nossa RN-DL-08
Propósito do endereçopartner rolescampo purposesflags billing / shipping / deliver-to siteTrês produtos, três formas da mesma ideia. Aqui não precisamos: o registro só existe para receber
Endereço eventualone-time delivery addressSó o SAP tem. Endereço divergente no pedido gera até uma one-time location na integração com o TM
Código e contato no localADRClocation-code, attention, activeLocationO attention line da Coupa é o nosso contactName, e existe pelo mesmo motivo prático
Grupo fiscal de entregalocalização brasileiraNenhum produto internacional modela o Grupo G da NF-e — é onde a localização brasileira sempre entra depois, como adaptação
Motivo interestadual declaradoNão existe em nenhum deles. É consequência de uma regra que só o Brasil tem, e é a única invenção desta spec

Três notas. A primeira: a separação em dois níveis aparece nos três produtos internacionais, com nomes diferentes — é a forma certa, e a nossa vantagem é que o nível fiscal já existia como Establishment antes de esta spec começar. A segunda: o endereço eventual é um caso em que o SAP está sozinho e certo — o caso é real, e negá-lo empurra a informação para o campo de observação. A terceira, e a que importa: a exigência de motivo para entrega interestadual não tem equivalente em nenhum dos quatro, porque nenhum deles nasceu num país onde a UF de destino muda a alíquota. É o mesmo tipo de vantagem estrutural que a spec de Empresa identificou nos dois níveis de CNPJ.

Limites

Fora de escopo

O quePor quê
Cálculo fiscal — ICMS, DIFAL, ST, FCP, CFOPO Nexio registra a dimensão e a entrega íntegra a quem calcula. Apurar imposto é do ERP fiscal, e entrar nisso multiplica a superfície de manutenção por 27 legislações estaduais
Agendamento de doca com capacidadereceivingHours é texto exibível e requiresScheduling é um aviso. Agenda com janelas, capacidade e reserva é produto próprio — e agenda que ninguém mantém é pior que uma frase certa
Roteirização, frete e transportadoraTransportadora é dado do pedido, não do ponto de entrega. Roteirização é TMS
Depósito e endereçamento de estoqueO storage location do SAP. Ponto de entrega responde onde chega; depósito responde onde fica. Estoque segue fora de escopo, com ItemType.controlsStock sempre false
Endereço fora do BrasilcountryCode existe e é sempre BR. Importação tem local de desembaraço, regime aduaneiro e moeda — é outro documento inteiro
ISS e local de prestação de serviçoGancho declarado. Em serviço o município decide a retenção, e a dimensão não é para onde a mercadoria vai. Quando o módulo de serviços existir, a checagem de UF ganha um irmão municipal
Endereço de cobrançaNão existe bill-to separado do lado comprador: a nota vem para o estabelecimento, e o endereço dele já está lá
GeolocalizaçãoCoordenadas servem a roteirização e a prova de entrega — as duas fora. Voltam com o módulo que as justificar
Ponto de entrega compartilhado entre empresasPor decisão, não por limitação: o mesmo galpão vira N registros, um por CNPJ destinatário, porque fiscalmente são N operações. Ver § Escopo e visibilidade