Pular para o conteúdo principal

Regras de Data de Entrega (Dalla) — AD_DTENTREGA

Ticket: [<Link do ticket>](<Link do ticket>) > Título: <Nome do ticket ou funcionalidade> > Última atualização: 30 de dezembro de 2025

Visão Geral

Este documento descreve as regras de cálculo e validação da data de entrega (AD_DTENTREGA) para a empresa/fluxo Dalla, implementadas em src/controllers/sale/create/delivery.sales.create.controller.ts.

As regras são utilizadas para:

  • calcular a data mínima sugerida de entrega por item (calculateDeliveryDate)
  • validar se uma data escolhida é permitida (validateDeliveryDate)
  • tratar exceções por faixa de datas (getContentIfDateWithinRange)

Componentes e Funções

FunçãoArquivoResponsabilidade
calculateDeliveryDatesrc/controllers/sale/create/delivery.sales.create.controller.tsCalcula uma data mínima de entrega considerando regras de prazo, capacidade, dias permitidos, exceções e feriados
validateDeliveryDatesrc/controllers/sale/create/delivery.sales.create.controller.tsValida se uma data específica é permitida para entrega
getContentIfDateWithinRangesrc/controllers/sale/create/delivery.sales.create.controller.tsDetermina se existe exceção ativa para a data e empresa de venda
getCodReg / getCodRegDallasrc/controllers/sale/create/header.sales.create.controller.tsDetermina a região (CODREG) usada para selecionar a regra correta

Entradas (parâmetros) e fontes no estado

1) Dados do Produto

CampoDescriçãoUso
AD_DTENTREGAData de entrega (DD/MM/YYYY)Recebe valor calculado ou escolhido pelo usuário
AD_ENTREGATipo de entregaInterfere no tipo de prazo aplicado
AD_ENCOMENDAIndicador de encomendaDefine prazo mínimo específico (PRAZOMINENTENCOM)
AD_CODEMPESTEmpresa estabelecimentoInterfere em regra de transferência e validação de capacidade
AD_CODEMPDESTEmpresa destinoChave para buscar regra de entrega (junto com CODREG)
AD_CODEMPORIGEmpresa origem/vendaUsada na busca de exceções (CODEMPVDA)

2) Dados do Pedido/Cliente

CampoOrigemUso
CODCONTATO / CODCONTATOENTREGAheaderUsado em getCodReg para determinar CODREG
clientstate.salesCreate.clientUsado na seleção de feriado por cidade e demais parâmetros

3) Tabelas auxiliares (utils)

Origem: state.salesCreateUtils

EstruturaDescrição
deliveryRulesRegras de entrega por chave ${CODREG}-${AD_CODEMPDEST}
exceptionsDeliveriesExceções por faixa de datas, com tipo de exceção e empresa de venda
shippingWeightControle de capacidade por data (peso total por empresa e data)
holidaysFeriados (geral e/ou por cidade)

Regra 1 — Seleção da regra de entrega (deliveryRules)

A seleção da regra é feita por:

  1. Determinação de CODREG via getCodReg(CODCONTATO, client).
  2. Busca da regra em deliveryRules utilizando a chave:
  • ${CODREG}-${AD_CODEMPDEST}

Trecho real:

const CODREG = getCodReg(CODCONTATO, client);
deliveryRule = deliveryRules?.[`${CODREG}-${AD_CODEMPDEST}`];

if (!deliveryRule) return "";

Leitura prática

  • Se não existir regra cadastrada para a combinação região + empresa destino, a função não calcula data e retorna vazio ('').

Regra 2 — Cálculo do prazo mínimo inicial

O algoritmo inicia a partir da data atual (dayjs()) e adiciona um prazo conforme o cenário:

2.1 Encomenda (AD_ENCOMENDA === 'S')

Aplica: PRAZOMINENTENCOM.

if (AD_ENCOMENDA === "S") {
deliveryDate = deliveryDate.add(deliveryRule.PRAZOMINENTENCOM, "day");
}

2.2 Transferência / regras especiais

Se:

  • AD_ENTREGA !== 'E' ou
  • há divergência entre AD_CODEMPEST e AD_CODEMPDEST com condições específicas

Aplica: PRAZOMINENTTRANSF.

Trecho real:

else if (
AD_ENTREGA !== 'E' ||
(AD_CODEMPEST !== AD_CODEMPDEST &&
((AD_CODEMPEST !== '4' && AD_CODEMPDEST !== '5' && AD_ENTREGA === 'E') ||
(AD_CODEMPEST !== '4' && AD_CODEMPDEST !== '11' && AD_ENTREGA === 'E') ||
(AD_CODEMPEST !== '4' && AD_CODEMPDEST !== '14' && AD_ENTREGA === 'E')))
) {
deliveryDate = deliveryDate.add(deliveryRule.PRAZOMINENTTRANSF, 'day')
}

2.3 Entrega padrão

Caso contrário, aplica: PRAZOMINENT.

else {
deliveryDate = deliveryDate.add(deliveryRule.PRAZOMINENT, 'day')
}

Leitura prática

  • Encomenda: prazo mínimo específico.
  • Cenários que exigem transferência/logística diferente: prazo mínimo de transferência.
  • Demais casos: prazo mínimo padrão.

Regra 3 — Busca do primeiro dia válido (loop com limitDays)

Após definir a data inicial, o cálculo incrementa 1 dia por vez até encontrar uma data válida.

Condição do loop:

  • enquanto dayjs().diff(deliveryDate, 'day') <= limitDays
  • e a data não for válida (validateDeliveryDate(...) === false)

Trecho real:

while (
dayjs().diff(deliveryDate, "day") <= limitDays &&
!validateDeliveryDate({
client,
date: deliveryDate,
holidays,
deliveryRule,
shippingWeight,
exceptionsDeliveries,
AD_CODEMPEST,
AD_CODEMPDEST,
AD_CODEMPORIG,
})
) {
deliveryDate = deliveryDate.add(1, "day");
}

No final, a função retorna a data no formato DD/MM/YYYY se válida, caso contrário retorna vazio.

if (validateDeliveryDate(...)) {
return deliveryDate.format('DD/MM/YYYY')
} else {
return ''
}

Regra 4 — Validação de data (validateDeliveryDate)

A validação de uma data passa pelas etapas abaixo, nesta ordem:

  1. Exceções (exceptionsDeliveries)
  2. Dia da semana permitido (deliveryRule.ENTDOM, ENTSEG, ...)
  3. Capacidade por data (shippingWeight x deliveryRule.CAPACIDADE)
  4. Feriados (holidays)

Regra 4.1 — Exceções por faixa de datas (exceptionsDeliveries)

A função getContentIfDateWithinRange procura uma exceção ativa para a data.

4.1.1 Formato das chaves

As exceções são percorridas por chave no formato:

  • DDMMYYYY-DDMMYYYY

Trecho real:

for (const key in exceptionsDeliveries) {
const [startDateStr, endDateStr] = key.split("-");
const startDate = dayjs(startDateStr, "DDMMYYYY");
const endDate = dayjs(endDateStr, "DDMMYYYY");
// ...
}

4.1.2 Filtro de empresa de venda (CODEMPVDA)

A exceção é aplicável quando:

  • CODEMPVDA é igual ao CODEMP (empresa origem/venda)
  • ou CODEMPVDA é '0' (regra geral)
if (
exceptionsDeliveries[key]?.CODEMPVDA?.toString() === CODEMP?.toString() ||
exceptionsDeliveries[key]?.CODEMPVDA?.toString?.() === "0"
) {
// ...
}

4.1.3 Verificação do intervalo

A exceção é retornada se a data estiver entre início e fim (inclusive):

if (
(dateCurrent.isSame(startDate) || dateCurrent.isAfter(startDate)) &&
(dateCurrent.isSame(endDate) || dateCurrent.isBefore(endDate))
) {
return exceptionsDeliveries[key];
}

4.1.4 Tipos de exceção

Quando existe exceção ativa:

  • TIPOEXCESSAO === 'B' → data bloqueada (retorna false)
  • TIPOEXCESSAO === 'P' → data permitida (retorna true)

Trecho real:

if (exception?.TIPOEXCESSAO === "B") {
return false;
} else if (exception?.TIPOEXCESSAO === "P") {
return true;
}

Regra 4.2 — Dias da semana permitidos

Após exceções, a validação checa se a transportadora/regra permite entrega no dia da semana.

Mapeamento:

  • date.day() === 0 → Domingo (ENTDOM)
  • date.day() === 1 → Segunda (ENTSEG)
  • ...
  • date.day() === 6 → Sábado (ENTSAB)

Trecho real:

if (
(deliveryRule.ENTDOM === "N" && date.day() === 0) ||
(deliveryRule.ENTSEG === "N" && date.day() === 1) ||
(deliveryRule.ENTTER === "N" && date.day() === 2) ||
(deliveryRule.ENTQUA === "N" && date.day() === 3) ||
(deliveryRule.ENTQUI === "N" && date.day() === 4) ||
(deliveryRule.ENTSEX === "N" && date.day() === 5) ||
(deliveryRule.ENTSAB === "N" && date.day() === 6)
) {
return false;
}

Quando visibleError === true, são exibidas mensagens via toast.error(...) com o dia bloqueado e a data.


Regra 4.3 — Capacidade por data (shippingWeight)

A validação verifica se a capacidade do dia foi excedida.

A busca seleciona o registro que corresponde a:

  • CODEMPENTREGA == AD_CODEMPEST
  • CODEMP == AD_CODEMPORIG
  • DATA == date.format('DD/MM/YYYY')

Trecho real:

const shippingWeightResult = shippingWeight.find(
(item) =>
item.CODEMPENTREGA?.toString() === AD_CODEMPEST?.toString() &&
item.CODEMP?.toString() === AD_CODEMPORIG?.toString() &&
item.DATA?.toString() === date.format("DD/MM/YYYY")
);

Se existir registro e PESOTOTAL >= CAPACIDADE, a data é inválida:

if (
shippingWeightResult &&
Number(shippingWeightResult.PESOTOTAL) >= Number(deliveryRule.CAPACIDADE)
) {
return false;
}

Regra 4.4 — Feriados (holidays)

A validação procura feriado cujo campo DTFERIADO começa com DDMM da data.

let holiday = Object?.values(holidays)?.find?.((item) =>
item?.DTFERIADO?.startsWith?.(date?.format?.("DDMM"))
);

4.4.1 Feriado por cidade

Se holiday.CODCID !== 0, o feriado só é aplicado quando holiday.CODCID === client.CODCID.

if (holiday?.CODCID !== 0 && holiday?.CODCID !== Number(client.CODCID)) {
holiday = undefined;
}

4.4.2 Filtro de registros válidos

O feriado é mantido quando o campo DTFERIADO contiver 1900 ou DDMMYYYY.

if (
!holiday?.DTFERIADO?.includes("1900") &&
!holiday?.DTFERIADO?.includes("DDMMYYYY")
) {
holiday = undefined;
}

Se o feriado for considerado, a data é inválida (e pode exibir mensagem em visibleError).

if (holiday) {
if (visibleError) {
toast.error("Data de entrega não pode ser um feriado");
}
return false;
}

Integração com a UI (Nova Venda)

A) Cálculo automático no carregamento de produto (Dalla)

Ao montar/atualizar produto no slice (src/store/sale-create.slice.ts), quando isDalla():

  • preenche campos AD_CODEMPORIG, AD_CODEMPEST, AD_CODEMPDEST
  • chama calculateDeliveryDate com limitDays: 45

Trecho real:

if (isDalla()) {
products[KEY].AD_CODEMPORIG = CODEMP?.toString() || "";
products[KEY].AD_CODEMPEST = CODEMP?.toString() || "";
products[KEY].AD_CODEMPDEST = CODEMP?.toString() || "";
products[KEY].AD_ENCOMENDA = "";

if (client) {
products[KEY].AD_DTENTREGA = calculateDeliveryDate({
AD_CODEMPDEST: products[KEY].AD_CODEMPDEST || "",
AD_CODEMPEST: products[KEY].AD_CODEMPEST || "",
AD_ENCOMENDA: products[KEY].AD_ENCOMENDA || "",
AD_CODEMPORIG: products[KEY].AD_CODEMPORIG || "",
AD_ENTREGA: products[KEY].AD_ENTREGA || "",
CODCONTATO: action?.payload?.CODCONTATO,
client,
limitDays: 45,
holidays,
shippingWeight,
deliveryRules,
exceptionsDeliveries,
});
} else {
products[KEY].AD_DTENTREGA = "";
}

products[KEY].AD_ENTREGA = "C";
products[KEY].CODLOCALORIG = CODEMP?.toString() === "4" ? "102" : "101";
}

B) Componente de data de entrega por item

No componente NewSaleProductsDeliveryDate:

  • minDate do datepicker é a data calculada por calculateDeliveryDate
  • ao alterar a data, chama validateDeliveryDate com visibleError: true

Arquivo: src/screens/nova-venda/components/Products/components/List/components/DeliveryDate/NewSaleProductsDeliveryDate.tsx.

Trecho real:

const dateDefault = getCalculateDeliveryDate()

<MobileDatePicker
minDate={dayjs(dateDefault, 'DD/MM/YYYY')}
onChange={handleChange}
value={dayjs(product?.AD_DTENTREGA, 'DD/MM/YYYY') || null}
/>

E validação ao trocar:

validateDeliveryDate({
// ...
visibleError: true,
});

C) Componente de Encomenda (checkbox)

No componente NewSaleProductsOrderCheckbox:

  • alterações em AD_ENCOMENDA, AD_CODEMPEST, AD_CODEMPDEST, AD_ENTREGA disparam recálculo da data

Arquivo: src/screens/nova-venda/components/Products/components/List/components/OrderCheckbox/NewSaleProductsOrderCheckbox.tsx.


Arquivos e locais que utilizam as regras

  • src/controllers/sale/create/delivery.sales.create.controller.ts

    • calculateDeliveryDate
    • validateDeliveryDate
    • getContentIfDateWithinRange
  • src/store/sale-create.slice.ts

    • uso de calculateDeliveryDate para preencher AD_DTENTREGA quando Dalla
  • src/screens/nova-venda/components/Products/components/List/components/DeliveryDate/NewSaleProductsDeliveryDate.tsx

    • usa calculateDeliveryDate (minDate) e validateDeliveryDate (validação em UI)
  • src/screens/nova-venda/components/Products/components/List/components/OrderCheckbox/NewSaleProductsOrderCheckbox.tsx

    • usa calculateDeliveryDate para recálculo ao alternar Encomenda