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.8 · 11/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

Dois fatos, dois campos. Quando outro CNPJ ou CPF recebe a mercadoria no lugar do destinatário, a operação é triangular em qualquer UF, e deliveryOperationType é obrigatório, com os casos que a legislação nomeia. Interestadual é derivado — UF de entrega diferente da do estabelecimento — e nunca passa calado: ou há recebedor distinto com a operação declarada, ou é canteiro de obra cadastrado com centro de custo, ou leva justificativa escrita. Sem nenhum dos três, 422. No endereço eventual o atalho do canteiro não vale: sem recebedor distinto, só a justificativa explica.

Decisão 4 · Terceiro

CNPJ de recebedor no ponto de entrega só quando outro contribuinte recebe. Industrializador, armazém geral, cliente em venda à ordem. CNPJ nosso é Establishment — 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. A única entrada para CNPJ do próprio grupo é a industrialização ou o armazém geral feitos por outra empresa do grupo (RN-DL-06).

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 à regra interestadual sem o atalho do canteiro: sem recebedor distinto, a justificativa é obrigatória. 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, recebedor e operação; 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 — industrialização por encomenda, armazém geral, venda à ordem ou remessa por conta e ordem de terceiros, todas com uma segunda NF-e que está fora do escopo do Nexio; 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 a operação declarada, a justificativa 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, UF e país, se a entrega é interestadual, destinatário fiscal, recebedor com IE, operação e justificativa. 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: code único por (tenantId, companyId) só entre os registros não excluídos — requisito; exemplo de implementação: índice único parcial filtrando isDeleted = false, ou, sem índice parcial, coluna gerada que só é preenchida nos não excluídos, com índice único sobre ela; 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 aceita recebedor — e o exige, com deliveryOperationType; ConstructionSite é o único que explica sozinho a entrega interestadual sem recebedor distinto, com centro de custo.
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 metade — 422.
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
isInterstateboolgeradoVerdadeiro quando stateCode difere do stateCode do estabelecimento. Nunca digitado; recalculado pela RN-DL-19 quando o estabelecimento muda de UF. Ver § Recebedor distinto e entrega interestadual.
deliveryOperationTypeenum?condObrigatório com type = ThirdParty, em qualquer UF, e recusado nos outros tipos. ThirdPartyProcessing · GeneralWarehouse · DirectToCustomer · Other (RN-DL-20).
deliveryOperationNotestring(400)?condObrigatória quando a operação é Other, recusada nas outras.
interstateNotestring(400)?condObrigatória quando isInterstate, sem recebedor distinto e fora de canteiro; opcional em canteiro interestadual cadastrado — no endereço eventual, obrigatória também em canteiro (RN-DL-12); recusada sem UF divergente e com recebedor distinto (RN-DL-05). É o campo que a auditoria lê primeiro.
recipientCnpjvarchar(14)?condObrigatório com type = ThirdParty e recusado nos outros tipos. CNPJ com a raiz de uma Company do tenant — cadastrado como Establishment ou não — é recusado, e a mensagem manda usá-lo, ou cadastrá-lo, como destinatário; salvo raiz de outra empresa do tenant em ThirdPartyProcessing ou GeneralWarehouse (RN-DL-06). VARCHAR, nunca numérico: CNPJ alfanumérico está em produção desde 31/07/2026. Normalizado antes de validar e de comparar, no mesmo padrão da Empresa: trim, sem máscara (saem ., / e -), letras em maiúsculas; depois, 14 caracteres — 12 em 0–9A–Z e 2 dígitos verificadores — e DV conferido com ASCII − 48. Formato ou DV inválido é 400 DELIVERY_LOCATION_RECIPIENT_CNPJ_INVALID. A comparação é feita entre os 8 primeiros caracteres do valor normalizado e o cnpjRoot das empresas do tenant.
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. 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. Inativo, o ponto não entra em documento novo; documento em andamento conclui com o que congelou (RN-DL-15).
versionintgeradoToken de concorrência — coluna inteira comum, incrementada a cada gravação. PUT, /activate, /deactivate e DELETE exigem expectedVersion; divergência é 409 DELIVERY_LOCATION_CONCURRENT_CHANGE_CONFLICT. A revalidação da RN-DL-19 também incrementa: quem editava o ponto enquanto a sede mudava relê antes de gravar.
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

Recebedor distinto e entrega interestadual

Duas perguntas, feitas nos três lugares em que um endereço de entrega nasce — ao salvar o ponto, ao usá-lo num documento e ao aceitar um endereço eventual. Quem recebe fisicamente é o destinatário? Quando não é, deliveryOperationType é obrigatório, em qualquer UF. A UF de entrega é a do estabelecimento? Quando não é, a entrega é interestadual — isInterstate, derivado e nunca digitado — e precisa estar explicada.

Recebedor distinto do destinatário · deliveryOperationType

OperaçãoO casoO que o Nexio faz
ThirdPartyProcessingIndustrialização por encomenda: a mercadoria vai direto ao industrializador, por conta e ordem do comprador.Exige type = ThirdParty, CNPJ e razão social do industrializador. Aceita CNPJ de estabelecimento de outra empresa do próprio grupo (RN-DL-06).
GeneralWarehouseArmazém geral: a mercadoria entra em depósito de pessoa jurídica que a guarda por conta do comprador.Idem, inclusive a entrada para CNPJ de outra empresa do grupo.
DirectToCustomerVenda à ordem ou remessa por conta e ordem de terceiros: o comprador já vendeu a mercadoria, e o fornecedor entrega direto ao cliente dele (drop ship).Exige type = ThirdParty e CNPJ no cadastro. É a única operação que aceita recebedor no endereço eventual, com CPF ou CNPJ no snapshot (RN-DL-18). CNPJ do próprio grupo é recusado: se a empresa do grupo é quem compra, ela é a destinatária.
OtherRecebedor distinto que a lista não nomeia.deliveryOperationNote obrigatória. CNPJ do próprio grupo é recusado. É o caso que a auditoria lê um por um, e é por isso que ele custa uma frase escrita.
O enum descreve o fato — alguém que não é o destinatário recebe — e nomeia os casos reconhecidos; não enquadra a operação. CFOP, a segunda NF-e (remessa simbólica, retorno, remessa por conta e ordem) e o tratamento de cada UF são do ERP fiscal e da assessoria do cliente. O enum é fechado de propósito: texto livre vira "conforme combinado" em 80% das linhas no terceiro mês, e aí a dimensão existe sem informar nada — que é o argumento do ReasonCode no mapa de domínio.

Entrega interestadual · isInterstate

SituaçãoO que explicaO que o Nexio exige
Com recebedor distintoA operação declarada em deliveryOperationType.Nada além dela. interstateNote é recusada: a operação já diz o que acontece.
Sem recebedor distinto, em canteirotype = ConstructionSite. 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.defaultCostCenterId obrigatório no cadastro (RN-DL-07); interstateNote opcional. Só no cadastro: no endereço eventual o tipo é digitado por quem pede e toda linha tem rateio, então canteiro não explica nada — ali a interstateNote é obrigatória (RN-DL-12).
Sem recebedor distinto, fora de canteiroO próprio destinatário recebe em outra UF: depósito sem inscrição própria, feira, funcionário remoto.interstateNote obrigatória, congelada no documento e marcada para auditoria. A recusa sugere o caminho certo quando ele existe: cadastrar um estabelecimento na UF de destino.
Sem UF divergente, interstateNote é recusada — justificativa que não justifica nada é ruído no relatório de auditoria.

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.

Mudar município, UF ou allowsReceiving do estabelecimento revalida todos os pontos

O stateCode do ponto sem endereço próprio é cópia, não leitura; e o isInterstate de qualquer ponto compara a UF dele com a do estabelecimento. Editar o cityIbgeCode do estabelecimento — mudança de sede ou correção de um código digitado errado — mexe nos dois: o ponto que herda muda de UF, e o ponto com endereço próprio em SP passa a ser interestadual quando a sede vai para MG.

Por isso o PUT do estabelecimento, quando muda município, UF ou allowsReceiving, revalida as RN-DL-05 e RN-DL-07 em todos os pontos pendurados nele — com e sem endereço próprio —, na mesma transação. allowsReceiving passando a falso com ponto ativo pendurado também recusa: o ponto apontaria para estabelecimento que deixou de receber, e a saída é desativar os pontos antes, o que nunca é recusado por documento (RN-DL-15). Recalcula o stateCode só nos que herdam e o isInterstate em todos. A justificativa dos pontos que passam a ser interestaduais vai no mesmo PUT, ponto a ponto — a nota não pode ser gravada antes, porque até a mudança a UF é a mesma e ela seria recusada. Faltando alguma, ou havendo canteiro que fica interestadual sem centro de custo, a edição é recusada com 422 e a lista nomeada. Ponto que deixa de ser interestadual tem a interstateNote limpa. Passando, sai um evento por ponto afetado, com os valores velho e novo de stateCode, isInterstate e interstateNote.

Documento emitido não muda, aqui como em todo lugar: o snapshot congelou a UF que valia, e a revalidação é do cadastro para a frente.

O Nexio avisa, não julga

O sistema não diz que a operação é legal — ele diz que outro contribuinte recebe, ou que a entrega é interestadual, e obriga alguém a declarar a operação ou a justificativa. 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, nenhuma justificativa é exigida 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. Declara o tipo do lugar (deliveryLocationType) e continua respondendo às duas perguntas: recebedor distinto só no caso da RN-DL-18, e entrega em outra UF explicada — sem o atalho do canteiro: no eventual interestadual sem recebedor distinto, interstateNote é sempre obrigatória, qualquer que seja o deliveryLocationType. O tipo do lugar é digitado por quem pede e toda linha tem rateio; aceitar "canteiro com o rateio da linha" como explicação deixaria mandar para outra UF sem nota só escolhendo o tipo. 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-locations-one-time é separada de lookup:delivery-locations. 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.

Dado pessoal no eventual: base declarada, guarda do documento e máscara

O eventual é onde o produto encontra dado pessoal: o endereço residencial do funcionário que recebe o notebook, o contato digitado e — só em DirectToCustomer — o CPF e o nome do consumidor final. O tenant é o controlador; o Nexio trata o dado como operador, e só o que a entrega e a nota precisam.

Base legal declarada (LGPD, art. 7º): execução de contrato de que o titular participa — a venda ao consumidor, o vínculo com quem recebe — e cumprimento de obrigação legal, porque o Grupo G da NF-e exige recebedor e endereço. A confirmação é do encarregado do cliente, como toda base legal. Guarda: os campos pessoais do snapshot seguem o prazo de guarda do documento dono; vencido esse prazo, são anonimizados — CPF, nome do recebedor pessoa física, contato, número e complemento —, e ficam CEP, município e UF, que sustentam relatório sem identificar ninguém. Nunca vão para evento, log ou texto de notificação.

Máscara na agregação: /one-time-usage mostra CPF só mascarado (***.456.789-**) e omite nome de pessoa física e contato — quem administra o catálogo precisa saber que o endereço se repete, não quem mora nele; o dado inteiro continua visível dentro do documento, para quem pode lê-lo. Grupo com recebedor pessoa física não oferece "cadastrar como ponto de entrega": o cadastro não guarda CPF, e /from-one-time recusa (RN-DL-21).

O que o eventual quase nunca faz. Não aceita recebedor distinto — entrega a outro contribuinte é decisão de cadastro, com CNPJ conferido, e não texto digitado às pressas na tela do pedido. A exceção é uma só: deliveryOperationType = DirectToCustomer (RN-DL-18). 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. Campos próprios, cada um consultável e indexável — não um documento semiestruturado numa coluna só: a UF e o CEP entram em índice e em relatório, e o documento aqui seria conveniência de escrita paga na leitura. É requisito, não recurso de banco (o jsonb do PostgreSQL ou o JSON em texto de outros bancos seriam o exemplo do que não se faz).
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.
deliveryCountryCodechar(2)ISO 3166-1, BR na v1. Congelado porque o Grupo G leva o país e a NT 2018.005 rejeita código inválido.
deliveryIsInterstateboolDerivado na criação — deliveryStateCode contra a UF do estabelecimento — e congelado. A sede que muda de UF depois não transforma em interna a entrega que foi interestadual.
deliveryLocationTypeenumO type do ponto; no eventual, o tipo declarado. Congelado porque, no ponto cadastrado, é ele que explica um canteiro interestadual sem justificativa escrita; no eventual, o tipo não dispensa a nota (RN-DL-12).
deliveryRecipientTaxId · deliveryRecipientNamevarchar(14)? · string(160)?Grupo G da NF-e, quando quem recebe não é o destinatário. Tax id e não CNPJ porque o drop ship a consumidor final põe um CPF no Grupo G; varchar(14) cobre os dois, e quem valida o dígito olha o comprimento. O campo do cadastro é recipientCnpj e é só CNPJ (RN-DL-06): é no snapshot que a pessoa física cabe, porque ali ela é um fato daquele documento (RN-DL-21).
deliveryRecipientStateRegistrationvarchar(20)?IE do recebedor, congelada. A nota leva a IE que valia na emissão, e é contra ela que a rejeição de IE inválida do grupo de entrega é evitada.
deliveryOperationType · deliveryOperationNoteenum? · string(400)?Congelados. É o que marca a linha para o relatório de operação triangular, em qualquer UF; mudar o cadastro depois não reescreve a operação que valeu naquele documento.
deliveryInterstateNotestring(400)?Congelada, pelo mesmo motivo. É a justificativa que a auditoria lê.
isOneTimeDeliveryboolVerdadeiro só no endereço eventual. É o que alimenta /one-time-usage.
deliveryLocationNamestring(160)O nome do ponto como estava na emissão. É a primeira linha do bloco de entrega no PDF, e renomear o ponto não pode reescrever o pedido que já saiu. No eventual, o nome digitado.
deliveryContactName · Phone · Emailstring?Quem recebe no local, congelado. É quem o motorista procura no portão — e quem o fornecedor liga quando não acha o portão. No eventual, dado pessoal com a guarda da RN-DL-21.
deliveryReceivingHoursstring(120)?A janela de recebimento impressa no pedido. Mudar o horário do cadastro não altera o compromisso que o pedido de agosto comunicou.
deliveryInstructionstext?Acesso, portaria, restrição de veículo, EPI — o texto que sai impresso.
deliveryRequiresSchedulingboolÉ contra este valor que o recebimento apura a divergência de agendamento, nunca contra o cadastro de hoje: entrega sem agendar só é divergência se o pedido tinha pedido agendamento. Ligar a exigência no cadastro em outubro não pode transformar em divergência a entrega combinada em agosto.
São vinte e seis colunas por linha — o bloco de endereço sozinho são seis. O tamanho é o ponto: o que o PDF do pedido imprime, o que o recebimento confere e o que a nota leva no Grupo G tem de estar aqui, porque a RN-DL-09 proíbe a exibição de ler o cadastro, e reconstruir por join depois de o cadastro mudar é impossível — que é a definição de snapshot no resto deste produto. São colunas, não documento semiestruturado: /one-time-usage agrupa por CEP e número, e a UF entra em índice e em relatório.

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 é interestadual explicado pelo próprio tipo, e exige 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 vinte e seis colunas de snapshot, deliveryLocationId no cabeçalho e por linha, e a validação de destinatário único. Documento gerado de outro — pedido da requisição, recebimento do pedido — herda o snapshot da origem (RN-DL-15), e o dono do documento anonimiza os campos pessoais do eventual ao fim da guarda (RN-DL-21). É 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 a justificativa no tooltip; ponto de terceiro mostra a operação ao lado do tipo.

Admin · cadastro

Estabelecimento primeiro, tudo depois — a UF dele e o tipo do ponto decidem se aparecem o bloco de recebedor e operação e o campo de justificativa interestadual. 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. CPF aparece mascarado, sem nome de pessoa física nem contato, e grupo com recebedor pessoa física não tem o botão.

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. Ponto interestadual mostra a explicação que o cadastro tem. No eventual, o tipo do lugar vem primeiro e decide o que a tela pede: recebedor e operação, ou justificativa quando a UF diverge.

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-locationsPagedResult<DeliveryLocationDto>, filtrável por empresa, estabelecimento, tipo, UF e vigência400
GET /delivery-locations/{id}read:delivery-locationsDeliveryLocationDto com o endereço efetivo — o próprio ou o herdado, resolvido no servidor404
GET /delivery-locations/lookuplookup:delivery-locationsO seletor. Só vigentes e ativos do estabelecimento pedido, agrupados, com stateCode e isInterstate de cada ponto400
POST /delivery-locationscreate:delivery-locationsDeliveryLocationDto400 · 404 · 409 · 422
PUT /delivery-locations/{id}update:delivery-locationsDeliveryLocationDto. establishmentId e code são recusados quando divergem. recipientCnpj fora do formato ou com DV inválido é 400 DELIVERY_LOCATION_RECIPIENT_CNPJ_INVALID; CEP ou código IBGE inválido, 400 (RN-DL-06)400 · 404 · 409 · 422
PATCH /delivery-locations/{id}/activateupdate:delivery-locationsEstado só por rota própria, nunca por PUT. Exige expectedVersion404 · 409 · 422
PATCH /delivery-locations/{id}/deactivatedelete:delivery-locationsExige expectedVersion. Nunca é recusada por documento em andamento (RN-DL-15)404 · 409
GET /delivery-locations/{id}/open-documentsread:delivery-locationsDocumentos em andamento que vão concluir com o ponto e rascunhos que vão precisar trocar de ponto antes de submeter, por tipo e com contagem. A tela mostra antes de desativar404
DELETE /delivery-locations/{id}delete:delivery-locationsExiste só para cadastro errado no mesmo dia. Com documento, é desativação404 · 409
GET /delivery-locations/one-time-usageread:delivery-locationsEndereços eventuais agrupados por CEP e número, com contagem e documentos. Janela padrão de 90 dias. CPF mascarado, sem nome de pessoa física nem contato (RN-DL-21)400
POST /delivery-locations/from-one-timecreate:delivery-locationsCria o cadastro a partir de um snapshot eventual. Não reescreve os documentos passados — eles continuam com o que congelaram. Recusa snapshot com recebedor pessoa física400 · 409 · 422
POST /delivery-locations:importcreate:delivery-locationsLote, 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 dez sufixos — _NOT_FOUND → 404 · _ALREADY_EXISTS, _ALREADY_ASSIGNED e _CONFLICT → 409 · _FORBIDDEN, _ACCESS_DENIED e _BLOCKED → 403 · _UNAUTHORIZED → 401 · _UNPROCESSABLE → 422 · _UNAVAILABLE → 503 · sem sufixo → 400. Código canônico explícito vence o sufixo. Nenhum código desta página usa _UNAVAILABLE.

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_CONFLICT409DELETE de ponto que algum documento já usou. A mensagem traz a contagem por tipo de documento e manda desativar — desativação não passa por aqui (RN-DL-15)
DELIVERY_LOCATION_CONCURRENT_CHANGE_CONFLICT409expectedVersion diferente da versão gravada, em PUT, /activate, /deactivate ou DELETE. A tela relê e mostra o que mudou
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_NOTE_REQUIRED_UNPROCESSABLE422Entrega interestadual sem recebedor distinto e sem interstateNote — no ponto cadastrado, fora de canteiro; no endereço eventual, em qualquer tipo de lugar (RN-DL-12). A mensagem sugere o caminho alternativo: cadastrar um estabelecimento na UF de destino
DELIVERY_LOCATION_INTERSTATE_NOTE_NOT_APPLICABLE_UNPROCESSABLE422interstateNote com UF igual à do estabelecimento, ou com recebedor distinto — a operação já explica
DELIVERY_LOCATION_OPERATION_TYPE_REQUIRED_UNPROCESSABLE422Recebedor distinto — type = ThirdParty no cadastro, recebedor no eventual — sem deliveryOperationType
DELIVERY_LOCATION_OPERATION_TYPE_NOT_APPLICABLE_UNPROCESSABLE422deliveryOperationType sem recebedor distinto
DELIVERY_LOCATION_OPERATION_NOTE_REQUIRED_UNPROCESSABLE422Operação Other sem deliveryOperationNote
DELIVERY_LOCATION_OPERATION_NOTE_NOT_APPLICABLE_UNPROCESSABLE422deliveryOperationNote em operação diferente de Other
DELIVERY_LOCATION_RECIPIENT_REQUIRED_UNPROCESSABLE422type = ThirdParty sem recipientCnpj ou sem recipientName
DELIVERY_LOCATION_RECIPIENT_NOT_ALLOWED_UNPROCESSABLE422recipientCnpj com type diferente de ThirdParty
DELIVERY_LOCATION_ONE_TIME_RECIPIENT_NOT_ALLOWED_UNPROCESSABLE422Recebedor no endereço eventual com deliveryOperationType diferente de DirectToCustomer. A mensagem diz qual é a única operação que o aceita (RN-DL-18)
DELIVERY_LOCATION_ONE_TIME_PERSONAL_RECIPIENT_UNPROCESSABLE422/from-one-time a partir de snapshot com recebedor pessoa física. O cadastro não guarda CPF (RN-DL-21)
DELIVERY_LOCATION_RECIPIENT_IS_OWN_ESTABLISHMENT_UNPROCESSABLE422O CNPJ do recebedor — recipientCnpj, ou deliveryRecipientTaxId de 14 caracteres no eventual — tem a raiz de uma Company do tenant fora da exceção da RN-DL-06: a raiz da empresa destinatária, ou a de outra empresa em operação que não é ThirdPartyProcessing nem GeneralWarehouse. Vale para estabelecimento cadastrado ou não. A mensagem nomeia a empresa e, quando cadastrado, o estabelecimento, e manda usá-lo como destinatário
ESTABLISHMENT_ADDRESS_CHANGE_BREAKS_DELIVERY_LOCATIONS_UNPROCESSABLE422PUT /establishments/{id} que muda município, UF ou allowsReceiving e deixaria algum ponto de entrega pendurado no estabelecimento — com ou sem endereço próprio — interestadual sem explicação (sem nota em deliveryLocationInterstateNotes[] no mesmo PUT, fora de canteiro e sem recebedor distinto; ou canteiro sem centro de custo), ou ativo e apontando para estabelecimento que deixou de receber. A mensagem lista os pontos pelo código e pelo nome (RN-DL-19, RN-EMP-17)
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 inativo ou fora da vigência na data do documento — na criação ou submissão do documento, ou ao incluir ou trocar o ponto de uma linha. Nomeia a linha. Documento já submetido não é revalidado (RN-DL-15)
DELIVERY_LOCATION_ONE_TIME_FORBIDDEN403Endereço eventual sem a permissão use:delivery-locations-one-time
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
DELIVERY_LOCATION_RECIPIENT_CNPJ_INVALID400recipientCnpj que, normalizado, não tem o formato do CNPJ ou tem DV inválido
DELIVERY_LOCATION_RECIPIENT_TAX_ID_INVALID400deliveryRecipientTaxId do eventual que, normalizado, não é CNPJ de 14 nem CPF de 11 válido

Autorização

Permissões

PermissãoAlcanceObservação
read:delivery-locationsListar e ler; abre a tela de cadastro e o relatório de endereços eventuaisRecortada pelo escopo do usuário. Não dá o seletor do documento: read e lookup não se implicam
lookup:delivery-locationsAlimentar o seletor de ponto de entrega do documento (GET /delivery-locations/lookup)Todo papel que emite documento precisa dela
create:delivery-locationsCriar, inclusive em lote por importação e a partir de um endereço eventualAdministração de cadastro. Separada de read pelo mesmo motivo de sempre
update:delivery-locationsEditar e ativarEstado só por rota própria; a ativação é update
delete:delivery-locationsDesativar e excluir o cadastro errado do mesmo diaDesativar é exclusão lógica e usa delete, mesmo sendo PATCH
use:delivery-locations-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
Seis 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-05Entrega interestadual é derivada e sempre explicada

isInterstate é verdadeiro quando stateCode difere do estabelecimento, e nunca é digitado. Interestadual exige uma de três explicações: recebedor distinto com deliveryOperationType (RN-DL-20); type = ConstructionSite com centro de custo, só no ponto cadastrado (RN-DL-07); ou interstateNote, a única explicação do endereço eventual sem recebedor distinto (RN-DL-12). Sem UF divergente, interstateNote é recusada; com recebedor distinto, também. Verificada no cadastro, no uso em documento e no endereço eventual — os três caminhos, sempre.

RN-DL-06CNPJ de recebedor só quando outro contribuinte recebe

recipientCnpj e recipientName são obrigatórios com type = ThirdParty e recusados nos outros tipos. CNPJ do próprio grupo é recusado — filial usada como endereço perde IE, Suframa e situação cadastral —, e o grupo é reconhecido pela raiz, não pelo cadastro: os 8 primeiros caracteres do recipientCnpj normalizado são comparados com o cnpjRoot de toda Company do tenant, esteja o estabelecimento cadastrado ou não. Raiz igual à da empresa destinatária — a do establishmentId — é sempre 422 DELIVERY_LOCATION_RECIPIENT_IS_OWN_ESTABLISHMENT_UNPROCESSABLE: a saída é cadastrar esse CNPJ como Establishment, se ainda não for, e usá-lo como destinatário. Raiz de outra Company do tenant é aceita só quando deliveryOperationType é ThirdPartyProcessing ou GeneralWarehouse — industrializador ou armazém do grupo é outro contribuinte, e é o CNPJ dele que vai no Grupo G —; em DirectToCustomer e Other, o mesmo 422. Sem a comparação por raiz, filial não cadastrada da própria empresa passaria como terceiro. recipientCnpj é normalizado antes de validar e de comparar — trim, sem máscara, maiúsculas — e formato ou DV inválido é 400 DELIVERY_LOCATION_RECIPIENT_CNPJ_INVALID; o deliveryRecipientTaxId do eventual segue a mesma normalização, como CNPJ de 14 ou CPF de 11, com 400 DELIVERY_LOCATION_RECIPIENT_TAX_ID_INVALID; com 14 caracteres, passa pela mesma comparação por raiz, e como o recebedor do eventual só existe em DirectToCustomer (RN-DL-18), raiz de qualquer Company do tenant é recusada com o mesmo 422.

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, país, UF, isInterstate, tipo do lugar, destinatário, recebedor com CPF ou CNPJ e IE, operação e justificativa vão para colunas da linha na criação — e também tudo o que o pedido impresso e o recebimento leem: nome do ponto, contato, janela de recebimento, instruções de acesso e a exigência de agendamento. A exibição do documento nunca lê o cadastro. A divergência de agendamento é apurada contra o snapshot, não contra o cadastro de hoje. 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-12Endereço eventual obedece às mesmas regras fiscais

Exige estabelecimento, declara o tipo do lugar, deriva stateCode do IBGE e cumpre a RN-DL-05 — sem o atalho do canteiro: interestadual sem recebedor distinto exige interstateNote qualquer que seja o deliveryLocationType declarado, senão 422 DELIVERY_LOCATION_INTERSTATE_NOTE_REQUIRED_UNPROCESSABLE. O tipo é digitado por quem pede e toda linha tem rateio, então "canteiro" não explica nada no eventual. O que ele dispensa é o cadastro, não o rigor. E não aceita recebedor distinto, salvo o caso único da RN-DL-18.

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 não emite documento novo; documento em andamento conclui

Com isActive = false, o ponto de entrega não é oferecido nem aceito em documento novo — criar ou submeter documento que o aponte, ou incluir ou trocar o ponto de uma linha, é recusado com 422 DELIVERY_LOCATION_NOT_EFFECTIVE_UNPROCESSABLE, nomeando a linha; submeter rascunho é documento novo, e o rascunho troca de ponto antes. Todo documento já submetido que o aponta segue até o fim: aprovação, pedido, recebimento, nota, devolução e estorno, com o snapshot congelado, que o documento gerado herda da origem sem reler o cadastro. A desativação não é recusada por haver documento em aberto; /open-documents mostra antes o que vai concluir com o ponto e quais rascunhos vão precisar trocar. É a mesma regra da empresa e do estabelecimento. Ponto fora de vigência segue a mesma regra. Documento fechado e histórico continuam legíveis com o que congelaram, com marca visual de ponto inativo.

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.

RN-DL-18Recebedor no eventual existe para um caso só: drop ship ao cliente final

O snapshot eventual aceita deliveryRecipientTaxId e deliveryRecipientName se e somente se deliveryOperationType = DirectToCustomer, com deliveryLocationType = ThirdParty; em qualquer outra operação é 422. Entrega direta ao cliente final é, por natureza, eventual — o comprador não volta a entregar naquele endereço. A exceção para aqui porque o consumidor final costuma ser pessoa física, e CPF em cadastro permanente é dado pessoal que o produto guardaria sem precisar: no snapshot ele é um fato daquele documento, que a nota vai carregar no Grupo G de qualquer forma, com a guarda e a máscara da RN-DL-21. 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 recebedor pessoa jurídica é revenda com carteira, e aí vira cadastro.

RN-DL-19Mudar município, UF ou allowsReceiving do estabelecimento revalida todos os pontos

O PUT do estabelecimento que altera cityIbgeCode, UF ou allowsReceiving revalida, na mesma transação, todos os pontos pendurados nele — com e sem endereço próprio. Recalcula stateCode só nos que herdam e isInterstate em todos, e confere neles as RN-DL-05 e RN-DL-07. A interstateNote de cada ponto que passa a ser interestadual vai no mesmo PUT, em deliveryLocationInterstateNotes[] — deliveryLocationId + interstateNote —; nota para ponto que não passa a interestadual é ignorada. A edição é recusada com 422 ESTABLISHMENT_ADDRESS_CHANGE_BREAKS_DELIVERY_LOCATIONS_UNPROCESSABLE e a lista nomeada quando falta nota, quando há canteiro sem centro de custo, ou quando allowsReceiving passa a falso com ponto ativo pendurado — que ficaria apontando para estabelecimento que deixou de receber; desative os pontos antes, o que nunca é recusado por documento (RN-DL-15). É o mesmo gatilho, o mesmo campo e o mesmo código que a Empresa declara na rota do estabelecimento (RN-EMP-17). Ponto que deixa de ser interestadual perde a interstateNote. Passando, a version de cada ponto afetado sobe e sai um evento por ponto. Documento emitido não muda.

RN-DL-20Recebedor distinto exige a operação declarada, em qualquer UF

Sempre que quem recebe fisicamente não é o destinatário — type = ThirdParty no cadastro, recebedor preenchido no eventual —, deliveryOperationType é obrigatório, independente da UF; sem recebedor distinto, é recusado. Other exige deliveryOperationNote. O enum nomeia o fato e os casos reconhecidos — industrialização, armazém geral, venda à ordem ou remessa por conta e ordem —; a segunda NF-e e o CFOP são do ERP fiscal. É o que marca a linha para o relatório de operação triangular, inclusive dentro da mesma UF.

RN-DL-21Dado pessoal do endereço eventual tem base, guarda e máscara

CPF, nome de pessoa física, contato e endereço residencial do snapshot eventual são tratados com base legal declarada (execução de contrato e obrigação legal da NF-e), seguem o prazo de guarda do documento dono e, vencido esse prazo, são anonimizados, restando CEP, município e UF. Nunca vão para evento, log ou notificação. /one-time-usage mostra CPF mascarado e omite nome de pessoa física e contato; /from-one-time a partir de snapshot com recebedor pessoa física é 422 DELIVERY_LOCATION_ONE_TIME_PERSONAL_RECIPIENT_UNPROCESSABLE.

Aferição

Referência de mercado

NexioSAPCoupaOracle FusionNota
Separação ship-to × deliver-toWerk / Lagerort × endereço de entrega no item—Ship-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 plant—o 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 address——Só 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 brasileira——Nenhum produto internacional modela o Grupo G da NF-e — é onde a localização brasileira sempre entra depois, como adaptação
Operação triangular e entrega interestadual explicadas———Nã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 operação declarada e de explicação 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
Segunda NF-e da operação triangularRemessa simbólica, retorno de industrialização, remessa por conta e ordem e depósito em armazém geral têm nota própria, emitida pelo fornecedor, pelo comprador ou pelo ERP fiscal. O Nexio registra a operação e o recebedor (RN-DL-20); não emite nem confere essa nota
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

Registro

Histórico de revisões

VersãoDataO que mudou
v1.930/10/2026Permissões padronizadas em read/lookup/create/update/delete (decisão de 30/10/2026). manage:delivery-locations vira, por ação: POST, POST /from-one-time e POST :import → create; PUT e PATCH /activate → update; PATCH /deactivate e DELETE → delete; GET /one-time-usage → read. O seletor GET /lookup passa de read a lookup:delivery-locations, e a tabela de permissões vai de três a seis linhas.
v1.811/09/2026Correção da validação R3. CNPJ do próprio grupo reconhecido pela raiz (cnpjRoot), cadastrado ou não: raiz da empresa destinatária sempre recusada; raiz de outra empresa só em industrialização e armazém geral; o deliveryRecipientTaxId de 14 caracteres do eventual passa pela mesma comparação (RN-DL-06). Unicidade do code escrita como requisito, com o índice parcial só como exemplo.
v1.711/09/2026Correção da validação R2. Endereço eventual interestadual sem recebedor distinto exige sempre interstateNote — canteiro declarado no eventual não explica (RN-DL-05, RN-DL-12). RN-DL-19 dispara também em allowsReceiving, e o texto do ESTABLISHMENT_ADDRESS_CHANGE_BREAKS_DELIVERY_LOCATIONS_UNPROCESSABLE é o mesmo da Empresa. deliveryAddress como requisito, sem recurso de banco; PUT /delivery-locations/{id} com o 400
v1.611/09/2026Correção pós-validação. recipientCnpj e deliveryRecipientTaxId normalizados antes de validar, com DELIVERY_LOCATION_RECIPIENT_CNPJ_INVALID e DELIVERY_LOCATION_RECIPIENT_TAX_ID_INVALID (400). DELIVERY_LOCATION_VERSION_CONFLICT passa a DELIVERY_LOCATION_CONCURRENT_CHANGE_CONFLICT; ONE_TIME_DELIVERY_NOT_PERMITTED_UNPROCESSABLE (422) passa a DELIVERY_LOCATION_ONE_TIME_FORBIDDEN (403). A nota dos pontos que passam a interestaduais na edição do estabelecimento ganha nome de campo comum com a Empresa, deliveryLocationInterstateNotes[], e código de recusa. O lookup deixa de falar em "motivo"
v1.510/09/2026Validação de 10/09. Sai IntraGroupTransfer e o interstateReason: nasce deliveryOperationType (recebedor distinto do destinatário, em qualquer UF) com deliveryOperationNote; interestadual passa a ser derivado (isInterstate) e explicado por operação, canteiro ou interstateNote (RN-DL-05, RN-DL-20). CNPJ de outra empresa do grupo aceito só em industrialização e armazém geral (RN-DL-06). Revalidação por mudança do estabelecimento cobre todos os pontos, com a justificativa no mesmo PUT (RN-DL-19). Desativar não trava documento em andamento (RN-DL-15) e /blocking-documents vira /open-documents. Snapshot de 21 para 26 colunas (país, IE do recebedor, tipo, isInterstate, justificativa). LGPD do endereço eventual (RN-DL-21). Token version. Erros do eventual duplicados unificados; dez sufixos.
v1.409/09/2026Ajustes de convenção do fechamento do ciclo de 08/09.
v1.309/09/2026Motivo IntraGroupTransfer (RN-DL-20); snapshot de 7 para 21 colunas; revalidação dos pontos que herdam ao mudar o município do estabelecimento (RN-DL-19); regra de destinatário no eventual renumerada de RN-DL-13 para RN-DL-18.
v1.208/09/2026Destinatário no endereço eventual para drop ship; deliveryRecipientCnpj renomeado para deliveryRecipientTaxId.
v1.002/09/2026Criação: DeliveryLocation pendurado no estabelecimento, regra interestadual, endereço eventual e snapshot na linha; preço por destino chaveado por UF no ItemSupplier.