$(document).ready(function () {
try {
FLUIGC.calendar('#dataNec');
} catch (e) {
console.warn("Erro ao iniciar calendário:", e);
}
toggleBotaoAddItem(); // inicia escondido
/* ========= Eventos ========= */
$('#precoRef, #quantidade').on('input', recalcTotal);
// formata o teto de preço só quando o usuário sair do campo
$('#precoRef').on('blur', function() {
const p = brMoneyToFloat($(this).val());
$(this).val(floatToBRL(p));
recalcTotal();
});
$('#qtdMais').on('click', function () {
let v = parseInt($('#quantidade').val() || '0', 10);
$('#quantidade').val(v + 1);
recalcTotal();
});
$('#qtdMenos').on('click', function () {
let v = parseInt($('#quantidade').val() || '0', 10);
v = Math.max(0, v - 1);
$('#quantidade').val(v);
recalcTotal();
});
$('#btnBuscaProd').on('click', consultarProdutos);
$('#btnLimpaProd').on('click', limparCamposPrincipais);
$('#btnAddItem').on('click', adicionarItem);
});
/* ========= Total / Quantidade ========= */
function recalcTotal() {
const q = parseFloat($('#quantidade').val() || '0');
const p = brMoneyToFloat($('#precoRef').val());
const t = (q * p) || 0;
$('#total').val(floatToBRL(t));
}
function setSelectedZoomItem(selectedItem) {
if (selectedItem.inputId === "estabelecimento") {
// dsFiliais: guarda dados da filial e define gestor da próxima atividade
var codigoProtheus = String(selectedItem.PROTHEUS || selectedItem.protheus || "").trim();
$("#filialdest").val(selectedItem.LOJA || "");
$("#filialest").val(selectedItem.UF || "");
$("#filialprotheus").val(codigoProtheus);
$("#centro_custo").val(selectedItem.RESPONSAVEL_LOJA || selectedItem.LOJA || "");
$("#codigocentroCusto").val(codigoProtheus);
var gestorLoja = (selectedItem.COLLEAGUE_ID || selectedItem.LOGIN_LOJA || "").trim();
$("#gestor_cc").val(gestorLoja);
if (!codigoProtheus) {
console.warn("Filial selecionada sem campo PROTHEUS no dsFiliais.");
}
}
}
function removedZoomItem(removedItem) {
if (removedItem.inputId === "estabelecimento") {
// Quando remover a filial, limpa os campos relacionados
$("#filialdest").val("");
$("#filialest").val("");
$("#filialprotheus").val("");
$("#centro_custo").val("");
$("#codigocentroCusto").val("");
$("#gestor_cc").val("");
}
}
/* ========= Config ========= */
const DATASET_PRODUTOS = "dsComprasProdutos"; // dataset de produtos
let todosProdutos = [];
let paginaAtual = 1;
const itensPorPagina = 10;
/* ========= Utils ========= */
function escapeHTML(txt) {
return $('
').text(txt == null ? '' : String(txt)).html();
}
function brMoneyToFloat(v) {
if (!v) return 0;
return parseFloat(
String(v)
.replace(/R\$/g, '') // remove "R$"
.replace(/\s/g, '') // remove espaços
.replace(/\./g, '') // remove pontos de milhar
.replace(',', '.') // troca vírgula por ponto
) || 0;
}
function floatToBRL(n) {
try {
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(n || 0);
} catch (_) {
return 'R$ ' + (n || 0).toFixed(2).replace('.', ',');
}
}
/* ========= Modal Consulta Produtos ========= */
function consultarProdutos() {
FLUIGC.modal({
title: 'Consulta de Produtos',
content:
'
' +
'' +
'
' +
'
' +
'
',
id: 'modalConsultaProdutos',
size: 'large',
actions: [{ 'label': 'Fechar', 'autoClose': true }]
}, function (err) {
if (!err) carregaListaProdutos();
});
}
function carregaListaProdutos(filtro) {
// Só chama o dataset se ainda não carregou nada
if (todosProdutos.length === 0) {
let dataset = DatasetFactory.getDataset(DATASET_PRODUTOS, null, null, null);
const values = dataset && dataset.values ? dataset.values : [];
todosProdutos = values
.map(normalizarProduto)
.filter(p => p.codigo && p.descricao);
console.log("Produtos carregados do dataset:", todosProdutos.length);
}
paginaAtual = 1;
renderizaProdutos(filtro);
}
function filtrarProdutos() {
paginaAtual = 1;
renderizaProdutos();
}
function renderizaProdutos(filtro) {
filtro = (filtro || $('#filtroDescricao').val() || '').toLowerCase();
// Agora filtra no cache (sem chamar dataset de novo)
const produtosFiltrados = todosProdutos.filter(p =>
(p.descricao || '').toLowerCase().includes(filtro) ||
(p.codigo || '').toLowerCase().includes(filtro) ||
(p.medida || '').toLowerCase().includes(filtro)
);
const inicio = (paginaAtual - 1) * itensPorPagina;
const fim = inicio + itensPorPagina;
const produtosPagina = produtosFiltrados.slice(inicio, fim);
let html = `
| Codigo |
Descricao |
UM |
Ultimo Preco |
Acao |
`;
if (produtosPagina.length === 0) {
html += `
|
Nenhum produto encontrado
|
`;
} else {
produtosPagina.forEach(produto => {
const codigo = escapeHTML(produto.codigo);
const descricao = escapeHTML(produto.descricao);
const um = escapeHTML(produto.medida || '');
const preco = produto.ultimo_preco || '0,00';
html += `
| ${codigo} |
${descricao} |
${um} |
${preco} |
|
`;
});
}
html += `
`;
$('#listaProdutos').html(html);
renderizaPaginacao(produtosFiltrados.length);
}
function normalizarProduto(row) {
return {
codigo: String(row.B1_COD || row.codigo || "").trim(),
descricao: String(row.B1_DESC || row.descricao || "").trim(),
medida: String(row.B1_UM || row.medida || "").trim(),
ultimo_preco: String(row.B1_UPRC || row.ultimo_preco || "0,00").trim()
};
}
function renderizaPaginacao(totalItens) {
const totalPaginas = Math.ceil(totalItens / itensPorPagina);
let html = '';
if (totalPaginas > 1) {
if (paginaAtual > 1) {
html += '
';
}
html += ' Pagina ' + paginaAtual + ' de ' + totalPaginas + ' ';
if (paginaAtual < totalPaginas) {
html += '
';
}
}
$('#paginacaoProdutos').html(html);
}
function mudarPagina(n) {
paginaAtual = n;
renderizaProdutos();
}
/* ========= Seleção ========= */
function selecionarProduto(codigo, descricao, preco) {
$('#produtoCod').val(codigo);
$('#descProduto').val(codigo + ' - ' + descricao);
$('#ultimoPreco').val(preco);
FLUIGC.toast({ title: 'Produto', message: 'Selecionado: ' + descricao, type: 'success' });
$('#modalConsultaProdutos').modal('hide');
toggleBotaoAddItem(); // 👈 mostra botão
}
function toggleBotaoAddItem() {
const temProduto = $('#produtoCod').val() || $('#descProduto').val();
if (temProduto && temProduto.trim() !== "") {
$('#btnAddItem').show();
} else {
$('#btnAddItem').hide();
}
}
/* ========= Adicionar Item ========= */
function adicionarItem() {
const cod = $('#produtoCod').val();
const desc = $('#descProduto').val();
const qtd = $('#quantidade').val();
if (!cod) {
FLUIGC.toast({ title: 'Atenção', message: 'Selecione um produto/serviço', type: 'warning' });
return;
}
const idx = wdkAddChild('tbItens');
setTimeout(() => {
$('input[name="Codproduto___' + idx + '"]').val(cod);
const somenteDesc = desc.includes('-') ? desc.split('-').slice(1).join('-').trim() : desc;
$('input[name="produtoDesc___' + idx + '"]').val(somenteDesc);
$('input[name="qtd___' + idx + '"]').val(qtd).on('input', function () { recalcLinha(this); });
$('input[name="ultimoPreco___' + idx + '"]').val(prec).on('input', function () { recalcLinha(this); });
atualizarIndex();
atualizarTotais();
}, 0);
FLUIGC.toast({ title: 'Item', message: 'Adicionado à lista', type: 'success' });
limparCamposPrincipais();
}
/* ========= Limpar campos principais ========= */
function limparCamposPrincipais() {
$('#produtoCod, #descProduto').val('');
$('#quantidade').val('0');
$('#precoRef').val('0,00');
$('#fnComprovante').val('');
toggleBotaoAddItem(); // 👈 mostra botão
}
/* ========= Eventos delegados ========= */
$(document).on('click', '.selecionar-produto', function () {
const codigo = $(this).data('codigo');
const descricao = $(this).data('descricao');
const preco = $(this).data('preco');
selecionarProduto(codigo, descricao, preco);
});
/* ========= Index das linhas ========= */
function atualizarIndex() {
$('#tbItens tbody tr.tableRow').each(function (i) {
if (!$(this).is('[detail=true]')) {
$(this).find('.tableIndex').text(i);
}
});
}
/* ========= Remover linha ========= */
function fnWdkRemoveChild(el) {
$(el).closest('tr').remove();
atualizarIndex();
atualizarTotais();
}
/* ========= Link do produto ========= */
function handleProductLink(el) {
const $row = $(el).closest("tr");
const $hidden = $row.find("input.produto-link");
let linkAtual = $hidden.val();
if (!linkAtual) {
// ainda não tem link → pedir ao usuário
let novoLink = prompt("Insira o link do produto:");
if (novoLink && novoLink.trim() !== "") {
$hidden.val(novoLink.trim()); // grava no hidden (vai persistir no Fluig)
}
} else {
// já existe link → abrir
window.open(linkAtual, "_blank");
}
}
$(function () {
var steps = [
{ state: 1, label: "Solicitação" },
{ state: 121, label: "Validando Necessidade" },
{ state: 82, label: "Enviando pedido" },
{ state: 114, label: "Cotação Iniciada" },
{ state: 105, label: "Indicar Cotação" },
{ state: 137, label: "Confirmação da cotação" },
{ state: 133, label: "Aprovação Gestor" },
{ state: 147, label: "Aprovação Ger. Financeiro" },
{ state: 158, label: "Aprovação CEO" },
{ state: 18, label: "Recebimento do Produto" },
{ state: 24, label: "Problema" },
{ state: 52, label: "Fim" }
];
var current = parseInt($("#activity").val() || "0", 10);
var idxAtual = steps.findIndex(function (s) { return s.state === current; });
if (idxAtual < 0) idxAtual = 0;
$("#wizard-steps .step-item").each(function (i) {
if (i < idxAtual) $(this).addClass("done");
if (i === idxAtual) $(this).addClass("active");
});
// clique nos steps
$("#wizard-steps .step-item").on("click", function () {
var index = $(this).index();
var step = steps[index];
if (!step) return;
// 👉 se já estava ativo, mostra tudo de novo
if ($(this).hasClass("active") && $(".activity:visible").length === 1) {
$(".activity").show();
$("#wizard-steps .step-item").removeClass("active");
return;
}
// senão, mostra só a activity clicada
$(".activity").hide();
$(".activity-" + step.state).show();
$("#wizard-steps .step-item").removeClass("active");
$(this).addClass("active");
});
});
function valorCampo(id) {
return String($("#" + id).val() || "").trim();
}
function setLabel(id, valor) {
var texto = String(valor || "").trim();
$("#" + id).text(texto || "-");
}
function badgeClassByStatus(status) {
var s = String(status || "").toLowerCase();
if (!s) return "badge bg-secondary";
if (s.indexOf("erro") >= 0 || s.indexOf("reprov") >= 0 || s.indexOf("cancel") >= 0) return "badge bg-danger";
if (s.indexOf("aguard") >= 0 || s.indexOf("pend") >= 0) return "badge bg-warning";
if (s.indexOf("sucesso") >= 0 || s.indexOf("aprov") >= 0 || s.indexOf("gerad") >= 0 || s.indexOf("liberad") >= 0) return "badge bg-success";
if (s.indexOf("bloque") >= 0 || s.indexOf("rejeit") >= 0) return "badge bg-danger";
return "badge bg-info";
}
function setBadge(selector, valor) {
var texto = String(valor || "").trim() || "-";
var classe = badgeClassByStatus(texto);
var textoLower = texto.toLowerCase();
// Mantem os badges de resumo da SC sem destaque verde para sucesso/geracao.
if (
(selector === "#statusSCProtheus_label" && textoLower.indexOf("sc cadastrada com sucesso") >= 0) ||
(selector === "#statusSC_label" && textoLower.indexOf("pedido gerado") >= 0)
) {
classe = "badge bg-info";
}
$(selector)
.text(texto)
.removeClass("bg-secondary bg-success bg-danger bg-warning bg-info")
.addClass(classe);
}
function normalizarStatusCadastro(statusCadastro, numeroSC) {
var numero = String(numeroSC || "").trim();
var status = String(statusCadastro || "").trim();
var s = status.toLowerCase();
if (!numero) return status;
if (!status) return "SC cadastrada com sucesso";
if (s.indexOf("sucesso") >= 0 || s.indexOf("cadastr") >= 0) return "SC cadastrada com sucesso";
return status;
}
function normalizarAndamento(andamento, cotacao, pedido) {
var atual = String(andamento || "").trim();
if (pedido) return "Pedido gerado";
if (cotacao && (!atual || atual.toLowerCase().indexOf("pedido") < 0)) return "Cotacao gerada";
return atual;
}
function normalizarDataProtheus(data) {
var d = String(data || "").trim();
if (/^\d{8}$/.test(d)) {
return d.substring(6, 8) + "/" + d.substring(4, 6) + "/" + d.substring(0, 4);
}
return d;
}
function limparNumeroDocumento(valor) {
var v = String(valor || "").trim();
if (!v || /^0+$/.test(v)) return "";
return v;
}
function normalizarCodigoComparacao(valor) {
var v = String(valor || "").trim();
if (!v) return "";
return v.replace(/^0+/, "");
}
function documentoEhPlaceholder(valor) {
var v = String(valor || "").trim().toUpperCase();
if (!v) return true;
if (v === "XXXX" || v === "XXXXXX") return true;
return /^X+$/.test(v);
}
function linhaCotacaoVencedora(row) {
var pedido = String(row.C8_NUMPED || "").trim();
var itemPedido = String(row.C8_ITEMPED || "").trim();
var fornece = String(row.C8_FORNECE || "").trim();
var loja = String(row.C8_LOJA || "").trim();
if (documentoEhPlaceholder(pedido)) return false;
if (documentoEhPlaceholder(itemPedido)) return false;
if (!fornece || !loja) return false;
return true;
}
function possuiFornecedorCotacao(row) {
var fornece = String(row.C8_FORNECE || "").trim();
var loja = String(row.C8_LOJA || "").trim();
return !!(fornece && loja);
}
function textoUtilFornecedor(valor) {
var txt = String(valor || "").trim();
if (!txt) return "";
if (txt === "-" || txt === "--") return "";
if (txt.toUpperCase() === "NULL") return "";
return txt;
}
function obterNomeFornecedorCompleto(row) {
var candidatos = [
textoUtilFornecedor(row.C8_FORNOME),
textoUtilFornecedor(row.A2_NOME),
textoUtilFornecedor(row.A2_NREDUZ)
].filter(function (v) { return !!v; });
if (!candidatos.length) return "";
candidatos.sort(function (a, b) {
if (b.length !== a.length) return b.length - a.length;
return a.localeCompare(b);
});
return candidatos[0];
}
function classificarLinhaCotacao(row) {
var status = String(row.STATUS || "").trim().toUpperCase();
if (linhaCotacaoVencedora(row)) {
return { tipo: "PEDIDO_GERADO", label: "GANHOU", badge: "badge bg-success", tipoFornecedor: "Fornecedor homologado" };
}
if (possuiFornecedorCotacao(row)) {
return { tipo: "FORNECEDOR_HOMOLOGADO", label: "Homologado", badge: "badge bg-info", tipoFornecedor: "Fornecedor homologado" };
}
if (status.indexOf("PEDIDO_GERADO") >= 0) {
return { tipo: "PERDEDOR", label: "", badge: "badge bg-warning", tipoFornecedor: "-" };
}
if (!possuiFornecedorCotacao(row)) {
return { tipo: "NOVO_FORNECEDOR", label: "Novo", badge: "badge bg-primary", tipoFornecedor: "Novo fornecedor" };
}
return { tipo: "EM_COTACAO", label: "EM COTACAO", badge: "badge bg-secondary", tipoFornecedor: "-" };
}
function formatarValorCotacao(valor) {
var txt = String(valor || "").trim();
if (!txt) return "-";
return floatToBRL(parseNumeroCotacao(txt));
}
function formatarDocumentoVisual(valor) {
var txt = String(valor || "").trim();
if (!txt || documentoEhPlaceholder(txt)) return "-";
return txt;
}
function classeCardCotacao(tipo) {
if (tipo === "PEDIDO_GERADO") return "sc-cotacao-card sc-cotacao-card--winner";
if (tipo === "FORNECEDOR_HOMOLOGADO") return "sc-cotacao-card sc-cotacao-card--homologado";
if (tipo === "NOVO_FORNECEDOR") return "sc-cotacao-card sc-cotacao-card--novo";
if (tipo === "PERDEDOR") return "sc-cotacao-card sc-cotacao-card--perdedor";
return "sc-cotacao-card";
}
function renderizarResumoCotacao(totalCotacoes, totalComPedido, menorTotal) {
var alvo = $("#cotacaoResultadoResumo");
if (!alvo.length) return;
var menorTxt = (menorTotal !== null) ? floatToBRL(menorTotal) : "-";
alvo.html([
'
',
' Quantidade',
' ' + escapeHTML(String(totalCotacoes || 0)) + "",
"
",
'
',
' Pedidos Gerados',
' ' + escapeHTML(String(totalComPedido || 0)) + "",
"
",
'
',
' Menor Valor',
' ' + escapeHTML(menorTxt) + "",
"
"
].join(""));
}
function comporDataHora(data, hora) {
var d = String(data || "").trim();
var h = String(hora || "").trim();
if (d && h && h !== "-") return d + " as " + h;
return d || h || "";
}
function montarEventosTimelineSC(dados) {
var eventos = [];
var momentoSolicitacao = comporDataHora(dados.dataCadastro, dados.horaCadastro);
var momentoSC = dados.emissao || momentoSolicitacao;
eventos.push({
classe: (dados.numero || dados.solicitante || momentoSolicitacao) ? "done" : "pending",
titulo: "Solicitacao criada",
momento: momentoSolicitacao,
detalhe: dados.solicitante ? "Solicitante: " + dados.solicitante : ""
});
if (dados.numero) {
eventos.push({
classe: "done",
titulo: "SC " + dados.numero + " cadastrada",
momento: momentoSC,
detalhe: dados.statusCadastro ? "Status: " + dados.statusCadastro : ""
});
} else {
eventos.push({
classe: "pending",
titulo: "Aguardando geracao da SC",
momento: "",
detalhe: "A SC sera exibida assim que for criada no Protheus."
});
}
if (dados.cotacao) {
eventos.push({
classe: "done",
titulo: "Cotacao " + dados.cotacao + " gerada",
momento: "",
detalhe: "Cotacao disponivel para analise."
});
} else {
eventos.push({
classe: "pending",
titulo: "Aguardando cotacao",
momento: "",
detalhe: "Ainda nao existe cotacao vinculada a SC."
});
}
if (dados.pedido) {
eventos.push({
classe: "done",
titulo: "Pedido " + dados.pedido + " gerado",
momento: "",
detalhe: "Compra convertida em pedido."
});
} else {
eventos.push({
classe: "pending",
titulo: "Aguardando pedido",
momento: "",
detalhe: "O pedido sera criado apos a aprovacao final da cotacao."
});
}
return eventos;
}
function renderizarTimelineSC(dados) {
var eventos = montarEventosTimelineSC(dados);
var html = eventos.map(function (evento) {
var titulo = escapeHTML(evento.titulo);
var momento = escapeHTML(evento.momento || "");
var detalhe = escapeHTML(evento.detalhe || "");
var classe = evento.classe === "done" ? "done" : "pending";
return [
'
',
' ',
' ' + titulo + '',
momento ? (' ' + momento + '') : "",
"
",
detalhe ? (' ' + detalhe + "
") : "",
""
].join("");
}).join("");
$("#scTimeline").html(html);
}
function renderizarResultadoCotacao(resumo) {
var badge = $("#cotacaoResultado_label");
var lista = $("#cotacaoResultadoLista");
if (!badge.length || !lista.length) return;
if (!resumo || !resumo.detalhes || !resumo.detalhes.length) {
setBadge("#cotacaoResultado_label", "Sem cotacao");
renderizarResumoCotacao(0, 0, null);
lista.html('
Aguardando vinculo da cotacao na SC.
');
return;
}
var statusResumo = "Sem fornecedor definido";
if ((resumo.qtdPedidoGerado || 0) > 0) {
statusResumo = "Cotacao concluida";
} else if ((resumo.qtdFornecedorHomologado || 0) > 0) {
statusResumo = "Fornecedor homologado em " + resumo.qtdFornecedorHomologado + " item(ns)";
} else if ((resumo.qtdNovoFornecedor || 0) > 0) {
statusResumo = "Novo fornecedor em " + resumo.qtdNovoFornecedor + " item(ns)";
}
setBadge("#cotacaoResultado_label", statusResumo);
var detalhesOrdenados = resumo.detalhes.slice().sort(function (a, b) {
var pesoA = (a.tipo === "PEDIDO_GERADO") ? 0 : 1;
var pesoB = (b.tipo === "PEDIDO_GERADO") ? 0 : 1;
if (pesoA !== pesoB) return pesoA - pesoB;
var totalA = parseNumeroCotacao(a.total);
var totalB = parseNumeroCotacao(b.total);
if (totalA === totalB) return 0;
return totalA - totalB;
});
var menorTotal = null;
var totalComPedido = 0;
for (var i = 0; i < detalhesOrdenados.length; i++) {
var t = parseNumeroCotacao(detalhesOrdenados[i].total);
if (t > 0 && (menorTotal === null || t < menorTotal)) menorTotal = t;
if (!documentoEhPlaceholder(detalhesOrdenados[i].pedido)) totalComPedido++;
}
renderizarResumoCotacao(detalhesOrdenados.length, totalComPedido, menorTotal);
var html = detalhesOrdenados.map(function (linha) {
var numeroTxt = escapeHTML(linha.numero || "-");
var itemTxt = escapeHTML(linha.item || "-");
var produtoTxt = escapeHTML(linha.produto || "-");
var fornecedorNomeTxt = escapeHTML(linha.fornecedorNome || linha.fornecedor || "Fornecedor nao informado");
var fornecedorTxt = escapeHTML(linha.fornecedor || "-");
var tipoFornecedorTxt = escapeHTML(linha.tipoFornecedor || "-");
var precoTxt = escapeHTML(formatarValorCotacao(linha.preco));
var totalTxt = escapeHTML(formatarValorCotacao(linha.total));
var pedidoTxt = escapeHTML(formatarDocumentoVisual(linha.pedido));
var statusApiTxt = escapeHTML(linha.statusApi || "-");
var statusRaw = String(linha.label || "").trim();
var statusTxt = escapeHTML(statusRaw);
var badgeStatus = linha.badge || "badge bg-secondary";
var classeCard = classeCardCotacao(linha.tipo);
var qtdTxt = escapeHTML(String(linha.quantidade || "-"));
var entregaTxt = escapeHTML(normalizarDataProtheus(linha.dataPrevista || ""));
var condicaoTxt = escapeHTML(linha.condicao || "-");
return [
'
',
' ',
"
",
'
' + fornecedorNomeTxt + "
",
'
Fornecedor: ' + fornecedorTxt + " | Tipo: " + tipoFornecedorTxt + "
",
"
",
statusRaw ? ('
' + statusTxt + "") : "",
"
",
' ",
' ",
""
].join("");
}).join("");
lista.html(html);
}
function renderizarErroCotacao(mensagem) {
var lista = $("#cotacaoResultadoLista");
if (!lista.length) return;
setBadge("#cotacaoResultado_label", "Erro consulta cotacao");
renderizarResumoCotacao(0, 0, null);
lista.html(
'
' +
escapeHTML(mensagem || "Nao foi possivel carregar a cotacao no momento.") +
"
"
);
}
function mapearStatusAlcada(codigo) {
var status = String(codigo || "").trim();
if (status === "01") return { label: "Pendente em niveis anteriores", badge: "badge bg-warning", classe: "pendente" };
if (status === "02") return { label: "Pendente", badge: "badge bg-warning", classe: "pendente" };
if (status === "03") return { label: "Aprovado", badge: "badge bg-success", classe: "aprovado" };
if (status === "04") return { label: "Bloqueado", badge: "badge bg-danger", classe: "bloqueado" };
if (status === "05") return { label: "Aprovado/rejeitado pelo nivel", badge: "badge bg-info", classe: "pendente" };
if (status === "06") return { label: "Rejeitado", badge: "badge bg-danger", classe: "bloqueado" };
if (status === "07") return { label: "Documento rejeitado ou bloqueado por outro usuario", badge: "badge bg-danger", classe: "bloqueado" };
return { label: status ? ("Status " + status) : "Sem status", badge: "badge bg-secondary", classe: "" };
}
function primeiroTextoPreenchido() {
for (var i = 0; i < arguments.length; i++) {
var txt = String(arguments[i] || "").trim();
if (txt) return txt;
}
return "";
}
function montarResumoRastreioPedido(pedidos, numeroPedido) {
if (!pedidos || !pedidos.length) return null;
var pedidoFiltro = normalizarCodigoComparacao(numeroPedido);
var pedidoBase = null;
for (var i = 0; i < pedidos.length; i++) {
var num = normalizarCodigoComparacao(String((pedidos[i] || {}).C7_NUM || ""));
if (!pedidoFiltro || num === pedidoFiltro) {
pedidoBase = pedidos[i];
break;
}
}
if (!pedidoBase) pedidoBase = pedidos[0];
var assinaturas = [];
var vistos = {};
for (var j = 0; j < pedidos.length; j++) {
var ped = pedidos[j] || {};
var alcadas = ped.ALCADAS || [];
for (var k = 0; k < alcadas.length; k++) {
var a = alcadas[k] || {};
var chave = [
String(a.CR_TIPO || "").trim(),
String(a.CR_USER || "").trim(),
String(a.CR_USERLIB || "").trim(),
String(a.CR_STATUS || "").trim(),
String(a.CR_PRAZO || "").trim(),
String(a.CR_DATALIB || "").trim()
].join("|");
if (vistos[chave]) continue;
vistos[chave] = true;
var statusInfo = mapearStatusAlcada(a.CR_STATUS);
assinaturas.push({
statusCodigo: String(a.CR_STATUS || "").trim(),
statusLabel: statusInfo.label,
badge: statusInfo.badge,
classe: statusInfo.classe,
tipo: String(a.CR_TIPO || "").trim(),
prazo: normalizarDataProtheus(a.CR_PRAZO),
dataLiberacao: normalizarDataProtheus(a.CR_DATALIB),
usuario: primeiroTextoPreenchido(a.CR_USER_NOME, a.AK_NOME, a.CR_USER),
usuarioLiberacao: primeiroTextoPreenchido(a.CR_USERLIB_NOME, a.AK_NOME_USERLIB, a.CR_USERLIB)
});
}
}
var resumo = {
numero: String(pedidoBase.C7_NUM || "").trim(),
statusPedido: String(pedidoBase.STATUS || "").trim(),
fornecedor: primeiroTextoPreenchido(pedidoBase.A2_NOME, pedidoBase.A2_NREDUZ, pedidoBase.C7_FORNECE),
emissao: normalizarDataProtheus(pedidoBase.C7_EMISSAO),
entrega: normalizarDataProtheus(pedidoBase.C7_DATPRF),
assinaturas: assinaturas
};
return resumo;
}
function renderizarErroRastreioPedido(mensagem) {
setBadge("#pedidoRastreio_label", "Erro no rastreio");
$("#pedidoRastreioResumo").text("Nao foi possivel consultar o rastreio do pedido.");
$("#pedidoRastreioAssinaturas").html(
'
' + escapeHTML(mensagem || "Erro ao consultar rastreio.") + "
"
);
}
function renderizarRastreioPedido(resumo) {
var badge = $("#pedidoRastreio_label");
var resumoEl = $("#pedidoRastreioResumo");
var lista = $("#pedidoRastreioAssinaturas");
if (!badge.length || !resumoEl.length || !lista.length) return;
if (!resumo || !resumo.numero) {
setBadge("#pedidoRastreio_label", "Sem pedido");
resumoEl.text("Sem pedido vinculado.");
lista.html('
Sem assinaturas para exibir.
');
return;
}
var possuiBloqueio = resumo.assinaturas.some(function (a) { return a.classe === "bloqueado"; });
var possuiPendente = resumo.assinaturas.some(function (a) { return a.classe === "pendente"; });
var todosAprovados = resumo.assinaturas.length > 0 && resumo.assinaturas.every(function (a) { return a.statusCodigo === "03"; });
var statusTopo = "Pedido pendente";
if (possuiBloqueio) statusTopo = "Pedido bloqueado";
else if (todosAprovados) statusTopo = "Pedido aprovado";
else if (!possuiPendente && resumo.statusPedido) statusTopo = resumo.statusPedido;
setBadge("#pedidoRastreio_label", statusTopo);
var resumoTxt = "Pedido " + (resumo.numero || "-");
if (resumo.fornecedor) resumoTxt += " | Fornecedor: " + resumo.fornecedor;
if (resumo.emissao) resumoTxt += " | Emissao: " + resumo.emissao;
if (resumo.entrega) resumoTxt += " | Entrega: " + resumo.entrega;
resumoEl.text(resumoTxt);
if (!resumo.assinaturas.length) {
lista.html('
Pedido encontrado, mas sem alcadas retornadas pela API.
');
return;
}
var html = resumo.assinaturas.map(function (a, idx) {
var classeCard = "sc-pedido-ass-card" + (a.classe ? (" " + a.classe) : "");
var nivel = "Nivel " + (idx + 1);
var usuario = escapeHTML(a.usuario || "-");
var usuarioLib = escapeHTML(a.usuarioLiberacao || "-");
var prazo = escapeHTML(a.prazo || "-");
var dataLib = escapeHTML(a.dataLiberacao || "-");
var tipo = escapeHTML(a.tipo || "-");
var statusLabel = escapeHTML(a.statusLabel || "-");
var badgeStatus = a.badge || "badge bg-secondary";
return [
'
',
' ",
' ',
' Tipo: ' + tipo + "",
' Prazo: ' + prazo + "",
' Data liberacao: ' + dataLib + "",
' Liberado por: ' + usuarioLib + "",
"
",
""
].join("");
}).join("");
lista.html(html);
}
function montarResumoCotacaoPorLinhas(rows, cotacao) {
if (!rows || !rows.length) return null;
var filtroCotacao = normalizarCodigoComparacao(cotacao);
var filtradas = rows.filter(function (row) {
var erro = String(row.erro || row.ERRO || "").trim();
if (erro) return false;
var sucesso = String(row.sucesso || row.SUCESSO || "").trim().toLowerCase();
if (sucesso === "false") return false;
var numeroLinha = normalizarCodigoComparacao(row.C8_NUM || "");
if (filtroCotacao && numeroLinha && numeroLinha !== filtroCotacao) return false;
var item = String(row.C8_ITEM || row.C8_ITEMSC || "").trim();
var fornecedor = String(row.C8_FORNECE || "").trim();
var pedido = String(row.C8_NUMPED || "").trim();
return !!(item || fornecedor || pedido);
});
if (!filtradas.length) return null;
var porItem = {};
var detalhes = [];
filtradas.forEach(function (row) {
var item = String(row.C8_ITEM || row.C8_ITEMSC || "").trim();
if (!item) return;
if (!porItem[item]) porItem[item] = [];
porItem[item].push(row);
var classif = classificarLinhaCotacao(row);
detalhes.push({
numero: String(row.C8_NUM || "").trim(),
item: item,
produto: String(row.B1_DESC || row.C8_DESCRI || row.C8_PRODUTO || "").trim(),
quantidade: String(row.C8_QUANT || "").trim(),
condicao: String(row.C8_COND || "").trim(),
dataPrevista: String(row.C8_DATPRF || "").trim(),
fornecedor: possuiFornecedorCotacao(row)
? (String(row.C8_FORNECE || "").trim() + "/" + String(row.C8_LOJA || "").trim())
: "",
fornecedorNome: obterNomeFornecedorCompleto(row),
preco: row.C8_PRECO,
total: row.C8_TOTAL,
pedido: String(row.C8_NUMPED || "").trim(),
statusApi: String(row.STATUS || "").trim(),
tipo: classif.tipo,
label: classif.label,
badge: classif.badge,
tipoFornecedor: classif.tipoFornecedor
});
});
var itens = [];
var qtdPedidoGerado = 0;
var qtdFornecedorHomologado = 0;
var qtdNovoFornecedor = 0;
Object.keys(porItem).sort().forEach(function (item) {
var linhas = porItem[item];
var vencedorPedido = null;
var fornecedorHomologado = null;
var fornecedorNovo = null;
for (var i = 0; i < linhas.length; i++) {
if (linhaCotacaoVencedora(linhas[i])) {
vencedorPedido = linhas[i];
break;
}
var fornece = String(linhas[i].C8_FORNECE || "").trim();
var loja = String(linhas[i].C8_LOJA || "").trim();
if (!fornecedorHomologado && fornece && loja) {
fornecedorHomologado = linhas[i];
}
if (!fornecedorNovo && !fornece && !loja) {
fornecedorNovo = linhas[i];
}
}
if (vencedorPedido) {
qtdPedidoGerado++;
itens.push({
item: item,
fornecedor: String(vencedorPedido.C8_FORNECE || "").trim() + "/" + String(vencedorPedido.C8_LOJA || "").trim(),
pedido: String(vencedorPedido.C8_NUMPED || "").trim(),
tipo: "PEDIDO_GERADO"
});
return;
}
if (fornecedorHomologado) {
qtdFornecedorHomologado++;
itens.push({
item: item,
fornecedor: String(fornecedorHomologado.C8_FORNECE || "").trim() + "/" + String(fornecedorHomologado.C8_LOJA || "").trim(),
pedido: String(fornecedorHomologado.C8_NUMPED || "").trim(),
tipo: "FORNECEDOR_HOMOLOGADO"
});
return;
}
if (fornecedorNovo) {
qtdNovoFornecedor++;
itens.push({
item: item,
fornecedor: String(fornecedorNovo.A2_NOME || fornecedorNovo.A2_NREDUZ || "").trim(),
pedido: String(fornecedorNovo.C8_NUMPED || "").trim(),
tipo: "NOVO_FORNECEDOR"
});
return;
}
itens.push({
item: item,
fornecedor: "",
pedido: "",
tipo: "EM_COTACAO"
});
});
return {
itens: itens,
detalhes: detalhes,
qtdPedidoGerado: qtdPedidoGerado,
qtdFornecedorHomologado: qtdFornecedorHomologado,
qtdNovoFornecedor: qtdNovoFornecedor
};
}
function consultarResultadoCotacao(cotacao) {
if (!cotacao || typeof DatasetFactory === "undefined" || typeof ConstraintType === "undefined") {
renderizarResultadoCotacao(null);
return;
}
try {
var cCotacao = DatasetFactory.createConstraint("numCotacao", cotacao, cotacao, ConstraintType.MUST);
var ds = DatasetFactory.getDataset("dsComprasCotacao", null, [cCotacao], null);
var rows = (ds && ds.values) ? ds.values : [];
if (!rows.length) {
renderizarResultadoCotacao(null);
return;
}
var erroLinha = rows.find(function (row) {
return String(row.erro || row.ERRO || "").trim();
});
if (erroLinha) {
renderizarErroCotacao(String(erroLinha.erro || erroLinha.ERRO || "").trim());
return;
}
renderizarResultadoCotacao(montarResumoCotacaoPorLinhas(rows, cotacao));
} catch (e) {
console.warn("Nao foi possivel consultar resultado da cotacao no dsComprasCotacao:", e);
renderizarResultadoCotacao(null);
}
}
function focarTimelineSC() {
var secao = $("#scTimelineSection");
if (!secao.length) return;
secao.addClass("is-focus");
setTimeout(function () {
secao.removeClass("is-focus");
}, 900);
try {
secao.get(0).scrollIntoView({ behavior: "smooth", block: "nearest" });
} catch (e) {
// fallback para navegadores sem smooth scroll
secao.get(0).scrollIntoView();
}
}
function abrirTimelineSC() {
var secao = $("#scTimelineSection");
if (!secao.length) return;
secao.addClass("is-open");
$("#cardNumeroSCHint").text("Clique para ocultar a linha do tempo");
}
function fecharTimelineSC() {
var secao = $("#scTimelineSection");
if (!secao.length) return;
secao.removeClass("is-open is-focus");
$("#cardNumeroSCHint").text("Clique para ver a linha do tempo");
}
function alternarTimelineSC() {
var secao = $("#scTimelineSection");
if (!secao.length) return;
if (secao.hasClass("is-open")) {
fecharTimelineSC();
return;
}
abrirTimelineSC();
focarTimelineSC();
}
function montarStatusAndamento(scRow, cotacao, pedido) {
if (pedido) return "Pedido gerado";
if (cotacao) return "Cotacao gerada";
var statusApi = String(scRow.STATUS || "").trim();
if (statusApi) return statusApi;
var aprov = String(scRow.C1_APROV || "").trim().toUpperCase();
if (aprov === "B") return "Aguardando cotacao";
if (aprov === "L") return "Liberada";
if (aprov === "R") return "Reprovada";
if (aprov) return "Status Protheus: " + aprov;
return "";
}
function preencherResumoSC(resumoCotacao, erroCotacao, resumoPedido, erroPedido) {
var numero = valorCampo("numeroSCProtheus");
var statusCadastro = valorCampo("statusSCProtheus");
var solicitante = valorCampo("solicitanteSCProtheus");
var emissao = normalizarDataProtheus(valorCampo("emissaoSCProtheus"));
var qtdItens = valorCampo("qtdItensSCProtheus");
var dataCadastro = normalizarDataProtheus(valorCampo("dataCadastroSCProtheus"));
var horaCadastro = valorCampo("horaCadastroSCProtheus");
var cotacao = limparNumeroDocumento(valorCampo("cotacaoSCProtheus"));
var pedido = limparNumeroDocumento(valorCampo("pedidoSCProtheus"));
var andamento = valorCampo("statusAtendimento");
var statusCadastroPadrao = normalizarStatusCadastro(statusCadastro, numero);
if (!andamento && numero) {
if (pedido) andamento = "Pedido gerado";
else if (cotacao) andamento = "Cotacao gerada";
else andamento = "Em andamento";
}
andamento = normalizarAndamento(andamento, cotacao, pedido);
setLabel("numeroSCProtheus_label", numero);
setLabel("solicitanteSCProtheus_label", solicitante);
setLabel("emissaoSCProtheus_label", emissao);
setLabel("qtdItensSCProtheus_label", qtdItens);
setLabel("dataCadastroSCProtheus_label", dataCadastro);
setLabel("horaCadastroSCProtheus_label", horaCadastro);
setLabel("cotacaoSC_label", cotacao);
setLabel("pedidoSC_label", pedido);
setBadge("#statusSCProtheus_label", statusCadastroPadrao || (numero ? "SC cadastrada com sucesso" : ""));
setBadge("#statusSC_label", andamento);
renderizarTimelineSC({
numero: numero,
statusCadastro: statusCadastroPadrao,
andamento: andamento,
solicitante: solicitante,
emissao: emissao,
dataCadastro: dataCadastro,
horaCadastro: horaCadastro,
cotacao: cotacao,
pedido: pedido
});
if (erroCotacao) {
renderizarErroCotacao(erroCotacao);
} else if (resumoCotacao && resumoCotacao.itens && resumoCotacao.itens.length) {
renderizarResultadoCotacao(resumoCotacao);
} else if (cotacao) {
consultarResultadoCotacao(cotacao);
} else {
renderizarResultadoCotacao(null);
}
if (erroPedido) {
renderizarErroRastreioPedido(erroPedido);
} else if (resumoPedido && resumoPedido.numero) {
renderizarRastreioPedido(resumoPedido);
} else {
renderizarRastreioPedido(null);
}
}
function consultarAndamentoSC() {
var numero = valorCampo("numeroSCProtheus");
if (!numero || typeof DatasetFactory === "undefined" || typeof ConstraintType === "undefined") {
return;
}
try {
var cNumero = DatasetFactory.createConstraint("numeroSCProtheus", numero, numero, ConstraintType.MUST);
var ds = DatasetFactory.getDataset("ds_consultaSC", null, [cNumero], null);
var row = (ds && ds.values && ds.values.length > 0) ? ds.values[0] : null;
if (!row) return;
if (String(row.sucesso || "").toLowerCase() !== "true") return;
var cotacao = limparNumeroDocumento(row.C1_COTACAO);
var pedido = limparNumeroDocumento(row.C1_PEDIDO);
if (cotacao) $("#cotacaoSCProtheus").val(cotacao);
if (pedido) $("#pedidoSCProtheus").val(pedido);
if (row.C1_SOLICIT) $("#solicitanteSCProtheus").val(String(row.C1_SOLICIT).trim());
if (row.C1_EMISSAO) $("#emissaoSCProtheus").val(normalizarDataProtheus(row.C1_EMISSAO));
var andamento = montarStatusAndamento(row, cotacao, pedido);
if (andamento) $("#statusAtendimento").val(andamento);
var resumoCotacao = null;
var erroCotacao = String(row.COTACAO_ERRO || "").trim();
var jsonCotacoes = String(row.COTACOES_JSON || "").trim();
if (jsonCotacoes) {
try {
var cotacoes = JSON.parse(jsonCotacoes);
resumoCotacao = montarResumoCotacaoPorLinhas(cotacoes, cotacao);
} catch (eCot) {
if (!erroCotacao) erroCotacao = "Falha ao ler cotacoes retornadas pelo ds_consultaSC";
}
}
var resumoPedido = null;
var erroPedido = String(row.PEDIDO_ERRO || "").trim();
var jsonPedido = String(row.PEDIDO_JSON || "").trim();
if (jsonPedido) {
try {
var pedidos = JSON.parse(jsonPedido);
resumoPedido = montarResumoRastreioPedido(pedidos, pedido);
} catch (ePed) {
if (!erroPedido) erroPedido = "Falha ao ler rastreio do pedido retornado pelo ds_consultaSC";
}
}
preencherResumoSC(resumoCotacao, erroCotacao, resumoPedido, erroPedido);
} catch (e) {
console.warn("Nao foi possivel consultar andamento da SC no ds_consultaSC:", e);
}
}
$(document).ready(function () {
preencherResumoSC();
consultarAndamentoSC();
$(document).on("click", "#cardNumeroSC", function () {
alternarTimelineSC();
});
});
function parseNumeroCotacao(valor) {
var texto = String(valor || "").trim();
if (!texto) return 0;
if (texto.indexOf(",") >= 0) {
texto = texto.replace(/\./g, "").replace(",", ".");
}
texto = texto.replace(/[^\d.-]/g, "");
return parseFloat(texto) || 0;
}
// garante que o total seja salvo antes de enviar a atividade
function beforeSendValidate(numState, nextState) {
var campoTotal = $("#valorTotalCotacao");
if (campoTotal.length && !String(campoTotal.val() || "").trim()) {
campoTotal.val("0").trigger("change");
}
return true;
}