This commit is contained in:
2026-03-11 17:54:14 -03:00
parent 9a0ef21ec8
commit 49491411f3
83 changed files with 5082 additions and 2776 deletions
@@ -305,6 +305,18 @@
color: #000000;
letter-spacing: 0.2px;
}
.pilar-score-badge {
margin-left: auto;
min-width: 68px;
padding: 3px 8px;
border-radius: 10px;
background: #edf4f8;
color: #0b5f79;
font-size: 11px;
font-weight: 800;
text-align: center;
line-height: 1.2;
}
.pilar-photo-row {
display: flex;
align-items: center;
@@ -336,6 +348,18 @@
background: #5d8fbe;
transition: width .18s ease;
}
.pilar-score-row {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 12px;
color: #243549;
}
.pilar-score-points {
font-size: 10px;
color: #000000;
font-weight: 600;
}
.pilar-foot {
display: flex;
align-items: center;
@@ -6,8 +6,13 @@
{ pilar: "PILAR ARQUITETURA", indicador: "Fotos dos mobshops", detalhe: "Mobiliário, gôndolas, tela digital, caixa, mesas, cavalete, baianas e coringa.", penalidade: "MEDIA", peso: 2, maxFotos: 2 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da vitrine", detalhe: " (Identificando todas as comunicações)", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Fotos enquadrando cada sessão", detalhe: "Feminina, masculina, infantil, cuidados, cabelos, presentes e maquiagem.", penalidade: "GRAVE", peso: 3, maxFotos: 7 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Fotos das comunicações destaques e storytelling", detalhe: "Feminina, masculina e cuidados.", penalidade: "GRAVE", peso: 3, maxFotos: 3 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da comunicação e destaque da sessão Feminina", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da comunicação e destaque da sessão Masculina", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da comunicação e destaque da sessão Infantil", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da comunicação e destaque da sessão Cuidados", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da comunicação e destaque da sessão Cabelos", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da comunicação e destaque da sessão Presentes", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da comunicação e destaque da sessão Maquiagem", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto das embalagens", penalidade: "MEDIA", peso: 2, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto do QR-Code de politica de privacidade", penalidade: "GRAVISSIMA", peso: 4, maxFotos: 1 },
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto do código de defesa do consumidor", penalidade: "GRAVISSIMA", peso: 4, maxFotos: 1 },
@@ -246,9 +251,10 @@
}
html += "<div class='pilar-panel'>";
html += "<div class='pilar-head' data-target='pilarBody" + p + "' data-total-fotos='" + totalFotosPilar + "'>";
html += "<div class='pilar-title-row'><span class='pilar-state-dot state-pending' title='Nao iniciado'>✕</span><span class='pilar-title'>" + escapeHtml(toTitleCase(nomePilar.replace("PILAR ", ""))) + "</span></div>";
html += "<div class='pilar-title-row'><span class='pilar-state-dot state-pending' title='Nao iniciado'>✕</span><span class='pilar-title'>" + escapeHtml(toTitleCase(nomePilar.replace("PILAR ", ""))) + "</span><span class='pilar-score-badge'>0.00%</span></div>";
html += "<div class='pilar-photo-row'><span class='pilar-photo-count'>0/" + totalFotosPilar + " fotos</span><span class='pilar-missing'>" + totalFotosPilar + " faltando</span></div>";
html += "<div class='pilar-mini-track'><span class='pilar-mini-fill'></span></div>";
html += "<div class='pilar-score-row'><span class='pilar-score-points'>0.00/0.00 pontos</span></div>";
html += "<div class='pilar-foot'><span class='pilar-count'>" + indicadorCountLabel(linhas.length) + "</span><span class='pilar-open-cta'>Abrir Pilar →</span></div>";
html += "</div>";
html += "<div class='pilar-body' id='pilarBody" + p + "'" + openStyle + ">";
@@ -330,6 +336,113 @@
return 0;
}
function getParamFromUrl(url, keys) {
var href = String(url || "");
if (!href || !keys || !keys.length) return "";
for (var i = 0; i < keys.length; i++) {
var re = new RegExp("(?:\\?|&)" + keys[i] + "=([^&#]+)", "i");
var m = href.match(re);
if (m && m[1]) return decodeURIComponent(m[1]);
}
return "";
}
function getProcessInstanceId() {
var candidates = [];
try {
candidates.push(window.WKNumProces);
candidates.push($("input[name='WKNumProces']").val());
candidates.push($("#WKNumProces").val());
candidates.push($("input[name='processInstanceId']").val());
candidates.push($("#processInstanceId").val());
candidates.push(getParamFromUrl(window.location && window.location.href, [
"app_ecm_workflowview_detailsProcessInstanceID",
"processInstanceId",
"WKNumProces"
]));
} catch (e) {}
try {
if (window.parent) {
candidates.push(window.parent.WKNumProces);
if (window.parent.$) {
candidates.push(window.parent.$("input[name='WKNumProces']").val());
candidates.push(window.parent.$("#WKNumProces").val());
candidates.push(window.parent.$("input[name='processInstanceId']").val());
candidates.push(window.parent.$("#processInstanceId").val());
}
candidates.push(getParamFromUrl(window.parent.location && window.parent.location.href, [
"app_ecm_workflowview_detailsProcessInstanceID",
"processInstanceId",
"WKNumProces"
]));
}
} catch (e2) {}
for (var j = 0; j < candidates.length; j++) {
var value = String(candidates[j] || "").trim();
if (value) return value;
}
return "";
}
function getProcessDefinitionId() {
var candidates = [];
try {
candidates.push($("input[name='processID']").val());
candidates.push($("#processID").val());
candidates.push($("input[name='processId']").val());
candidates.push($("#processId").val());
candidates.push(getParamFromUrl(window.location && window.location.href, [
"processID",
"processId"
]));
} catch (e) {}
try {
if (window.parent) {
if (window.parent.$) {
candidates.push(window.parent.$("input[name='processID']").val());
candidates.push(window.parent.$("#processID").val());
candidates.push(window.parent.$("input[name='processId']").val());
candidates.push(window.parent.$("#processId").val());
}
candidates.push(getParamFromUrl(window.parent.location && window.parent.location.href, [
"processID",
"processId"
]));
}
} catch (e2) {}
for (var j = 0; j < candidates.length; j++) {
var value = String(candidates[j] || "").trim();
if (value) return value;
}
return "";
}
function isRealProcessValue(value) {
var v = String(value || "").trim();
return !!v && v !== "0" && v.toLowerCase() !== "null" && v.toLowerCase() !== "undefined";
}
function fillProcessMetaIfAvailable() {
var processInstanceId = String(getProcessInstanceId() || "").trim();
var processDefinitionId = String(getProcessDefinitionId() || "").trim();
if (isRealProcessValue(processInstanceId)) {
$("#numeroSolicitacao").val(processInstanceId);
} else {
$("#numeroSolicitacao").val("");
}
if (isRealProcessValue(processDefinitionId)) {
$("#processId").val(processDefinitionId);
} else {
$("#processId").val("");
}
}
function getCurrentState() {
var candidates = [];
try {
@@ -400,29 +513,126 @@
return "LOJA";
}
function getCurrentUserLogin() {
function getCurrentUserDisplayName() {
try {
if (window.WCMAPI && window.WCMAPI.user) {
return String(window.WCMAPI.user).trim();
}
} catch (e) {}
try {
if (window.WCMAPI && window.WCMAPI.user) {
return String(window.WCMAPI.user);
try {
if (window.parent && window.parent.WCMAPI && window.parent.WCMAPI.user) {
return String(window.parent.WCMAPI.user).trim();
}
} catch (e2) {}
return "";
}
function readFirstValue(selectors, root) {
if (!root || !root.$) return "";
for (var i = 0; i < selectors.length; i++) {
try {
var value = String(root.$(selectors[i]).val() || "").trim();
if (value) return value;
} catch (e) {}
}
} catch (e) {}
return "";
}
try {
if (window.parent && window.parent.WCMAPI && window.parent.WCMAPI.user) {
return String(window.parent.WCMAPI.user);
function isNumericUserCode(value) {
return /^\d+$/.test(String(value || "").trim());
}
function resolveLoginFromColleagueId(colleagueId, callback) {
var id = String(colleagueId || "").trim();
if (!id) {
callback("");
return;
}
} catch (e2) {}
return "";
}
$.ajax({
url: "/api/public/ecm/dataset/datasets",
method: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify({
name: "colleague",
fields: ["login"],
constraints: [
{ _field: "colleaguePK.colleagueId", _initialValue: id, _finalValue: id, _type: 1 },
{ _field: "active", _initialValue: "true", _finalValue: "true", _type: 1 }
],
order: []
}),
success: function (res) {
var values = [];
if (res && res.content && $.isArray(res.content.values)) values = res.content.values;
else if (res && $.isArray(res.values)) values = res.values;
var login = values.length ? String(values[0].login || "").trim() : "";
callback(login || id);
},
error: function () {
callback(id);
}
});
}
function getCurrentUserLogin(callback) {
var selectors = [
"input[name='WKUser']",
"#WKUser",
"input[name='wkuser']",
"#wkuser"
];
var login = readFirstValue(selectors, window);
if (login) {
callback(login);
return;
}
login = readFirstValue(selectors, window.parent);
if (login) {
callback(login);
return;
}
var userCode = "";
try {
if (window.WCMAPI && window.WCMAPI.userCode) {
userCode = String(window.WCMAPI.userCode).trim();
}
} catch (e3) {}
if (!userCode) {
try {
if (window.parent && window.parent.WCMAPI && window.parent.WCMAPI.userCode) {
userCode = String(window.parent.WCMAPI.userCode).trim();
}
} catch (e4) {}
}
if (!userCode) {
callback("");
return;
}
if (!isNumericUserCode(userCode)) {
callback(userCode);
return;
}
resolveLoginFromColleagueId(userCode, callback);
}
function fillAuditorFromLoggedUser() {
var userCode = getCurrentUserLogin();
if (!userCode) return;
var userName = getCurrentUserDisplayName();
if (!userName) return;
var $auditor = $("#auditor");
if (!String($auditor.val() || "").trim()) {
$auditor.val(userCode);
$auditor.val(userName);
}
$auditor.prop("readonly", true);
}
@@ -522,6 +732,9 @@
$("#responsavelLoja").val(String(row.RESPONSAVEL_LOJA || "").trim());
}
$("#regional").val(String(row.REGIONAL || "").trim());
$("#uf").val(String(row.UF || row["UF 2"] || "").trim());
$("#canal").val(String(row.CANAL || "").trim());
$("#cidade").val(String(row.CIDADE || "").trim());
}
function initLojasFromApi() {
@@ -606,6 +819,7 @@
$("#globalProgressPercent").text(perc + "%");
$("#globalProgressMeta").text(preenchidos + " de " + total + " fotos enviadas");
updatePilarProgress();
updatePilarScores();
}
function updateRowAttachmentProgress($row) {
@@ -658,6 +872,45 @@
});
}
function updatePilarScores() {
var resumoPilares = {};
$(".pilar-panel").each(function () {
var $panel = $(this);
var pontosObtidos = 0;
var pontosPossiveis = 0;
var nomePilar = "";
$panel.find(".audit-row").each(function () {
var $row = $(this);
var peso = parseFloat($row.find(".peso").text()) || 0;
var resultado = String($row.find(".resultado").val() || "").trim();
var fator = FATORES[resultado];
if (!nomePilar) {
nomePilar = String($row.attr("data-pilar") || "").trim();
}
if (peso <= 0) return;
pontosPossiveis += peso;
if (typeof fator === "number") {
pontosObtidos += (peso * fator);
}
});
var percentual = pontosPossiveis > 0 ? ((pontosObtidos / pontosPossiveis) * 100) : 0;
$panel.find(".pilar-score-points").text(pontosObtidos.toFixed(2) + "/" + pontosPossiveis.toFixed(2) + " pontos");
$panel.find(".pilar-score-badge").text(percentual.toFixed(2) + "%");
if (nomePilar) {
resumoPilares[nomePilar] = {
obtidos: Number(pontosObtidos.toFixed(2)),
possiveis: Number(pontosPossiveis.toFixed(2)),
score: Number(percentual.toFixed(2))
};
}
});
$("#scorePilares").val(JSON.stringify(resumoPilares));
}
function initAttachmentPlugin() {
if (typeof $.fn.fluigFormAttachment !== "function") {
FLUIGC.toast({
@@ -910,6 +1163,7 @@
$("#pontosPossiveis").text(pontosPossiveis.toFixed(2));
$("#scoreFinal").text(score.toFixed(2) + "%");
$("#classificacao").text(getClassificacao(score));
updatePilarScores();
}
function validarFormulario() {
@@ -1033,9 +1287,14 @@
var wkState = getCurrentState();
CURRENT_PROFILE = resolveProfileByState(wkState);
fillDataAuditoriaTodayIfEmpty();
fillProcessMetaIfAvailable();
fillAuditorFromLoggedUser();
if (!($("#usuarioRetorno").val() || "").trim()) {
$("#usuarioRetorno").val(getCurrentUserLogin());
getCurrentUserLogin(function (login) {
if (login) {
$("#usuarioRetorno").val(login);
}
});
}
montaTabela();
initAttachmentPlugin();
@@ -1133,8 +1392,11 @@
if (selectedItem.inputId !== "loja" && selectedItem.inputName !== "loja") return;
$("#responsavelLoja").val(String(selectedItem.RESPONSAVEL_LOJA || "").trim());
$("#regional").val(String(selectedItem.REGIONAL || "").trim());
$("#uf").val(String(selectedItem.UF || selectedItem["UF 2"] || "").trim());
$("#canal").val(String(selectedItem.CANAL || "").trim());
$("#cidade").val(String(selectedItem.CIDADE || "").trim());
var loginLoja = String(selectedItem.LOGIN_LOJA || "").trim();
var colleagueId = String(selectedItem.COLLEAGUE_LOGIN || "").trim();
var colleagueId = String(selectedItem.COLLEAGUE_ID || "").trim();
if (!loginLoja) {
loginLoja = toLojaLoginFromPdv(selectedItem.PDV);
}
@@ -1155,6 +1417,9 @@
if (removedItem.inputId !== "loja" && removedItem.inputName !== "loja") return;
$("#responsavelLoja").val("");
$("#regional").val("");
$("#uf").val("");
$("#canal").val("");
$("#cidade").val("");
$("#destinoLoja").val("");
$("#destinoLojaId").val("");
try {
@@ -153,10 +153,16 @@
<input type="hidden" name="temNaoConforme" id="temNaoConforme" value="false" />
<input type="hidden" name="qtdNaoConforme" id="qtdNaoConforme" value="0" />
<input type="hidden" name="listaNaoConforme" id="listaNaoConforme" value="" />
<input type="hidden" name="scorePilares" id="scorePilares" value="" />
<input type="hidden" name="saidaAnalise" id="saidaAnalise" value="CONFORME" />
<input type="hidden" name="usuarioRetorno" id="usuarioRetorno" value="" />
<input type="hidden" name="destinoLoja" id="destinoLoja" value="" />
<input type="hidden" name="destinoLojaId" id="destinoLojaId" value="" />
<input type="hidden" name="numeroSolicitacao" id="numeroSolicitacao" value="" />
<input type="hidden" name="processId" id="processId" value="" />
<input type="hidden" name="uf" id="uf" value="" />
<input type="hidden" name="canal" id="canal" value="" />
<input type="hidden" name="cidade" id="cidade" value="" />
</div>
</form>
</div>