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ção | Arquivo | Responsabilidade |
|---|---|---|
calculateDeliveryDate | src/controllers/sale/create/delivery.sales.create.controller.ts | Calcula uma data mínima de entrega considerando regras de prazo, capacidade, dias permitidos, exceções e feriados |
validateDeliveryDate | src/controllers/sale/create/delivery.sales.create.controller.ts | Valida se uma data específica é permitida para entrega |
getContentIfDateWithinRange | src/controllers/sale/create/delivery.sales.create.controller.ts | Determina se existe exceção ativa para a data e empresa de venda |
getCodReg / getCodRegDalla | src/controllers/sale/create/header.sales.create.controller.ts | Determina a região (CODREG) usada para selecionar a regra correta |
Entradas (parâmetros) e fontes no estado
1) Dados do Produto
| Campo | Descrição | Uso |
|---|---|---|
AD_DTENTREGA | Data de entrega (DD/MM/YYYY) | Recebe valor calculado ou escolhido pelo usuário |
AD_ENTREGA | Tipo de entrega | Interfere no tipo de prazo aplicado |
AD_ENCOMENDA | Indicador de encomenda | Define prazo mínimo específico (PRAZOMINENTENCOM) |
AD_CODEMPEST | Empresa estabelecimento | Interfere em regra de transferência e validação de capacidade |
AD_CODEMPDEST | Empresa destino | Chave para buscar regra de entrega (junto com CODREG) |
AD_CODEMPORIG | Empresa origem/venda | Usada na busca de exceções (CODEMPVDA) |
2) Dados do Pedido/Cliente
| Campo | Origem | Uso |
|---|---|---|
CODCONTATO / CODCONTATOENTREGA | header | Usado em getCodReg para determinar CODREG |
client | state.salesCreate.client | Usado na seleção de feriado por cidade e demais parâmetros |
3) Tabelas auxiliares (utils)
Origem: state.salesCreateUtils
| Estrutura | Descrição |
|---|---|
deliveryRules | Regras de entrega por chave ${CODREG}-${AD_CODEMPDEST} |
exceptionsDeliveries | Exceções por faixa de datas, com tipo de exceção e empresa de venda |
shippingWeight | Controle de capacidade por data (peso total por empresa e data) |
holidays | Feriados (geral e/ou por cidade) |
Regra 1 — Seleção da regra de entrega (deliveryRules)
A seleção da regra é feita por:
- Determinação de
CODREGviagetCodReg(CODCONTATO, client). - Busca da regra em
deliveryRulesutilizando 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_CODEMPESTeAD_CODEMPDESTcom 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:
- Exceções (
exceptionsDeliveries) - Dia da semana permitido (
deliveryRule.ENTDOM,ENTSEG, ...) - Capacidade por data (
shippingWeightxdeliveryRule.CAPACIDADE) - 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 aoCODEMP(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 (retornafalse)TIPOEXCESSAO === 'P'→ data permitida (retornatrue)
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_CODEMPESTCODEMP==AD_CODEMPORIGDATA==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
calculateDeliveryDatecomlimitDays: 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:
minDatedo datepicker é a data calculada porcalculateDeliveryDate- ao alterar a data, chama
validateDeliveryDatecomvisibleError: 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_ENTREGAdisparam 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.tscalculateDeliveryDatevalidateDeliveryDategetContentIfDateWithinRange
-
src/store/sale-create.slice.ts- uso de
calculateDeliveryDatepara preencherAD_DTENTREGAquando Dalla
- uso de
-
src/screens/nova-venda/components/Products/components/List/components/DeliveryDate/NewSaleProductsDeliveryDate.tsx- usa
calculateDeliveryDate(minDate) evalidateDeliveryDate(validação em UI)
- usa
-
src/screens/nova-venda/components/Products/components/List/components/OrderCheckbox/NewSaleProductsOrderCheckbox.tsx- usa
calculateDeliveryDatepara recálculo ao alternar Encomenda
- usa