diff --git a/Transferência Ginseng/.vscode/servers.json b/Transferência Ginseng/.vscode/servers.json
index e88a557..d5fb634 100644
--- a/Transferência Ginseng/.vscode/servers.json
+++ b/Transferência Ginseng/.vscode/servers.json
@@ -2,13 +2,13 @@
"version": "1.0.0",
"configurations": [
{
- "id": "edmoa4q9botmmtlvdz4bafosc5mqmr",
- "name": "teste",
+ "id": "mkjw3cu0krommujt2hvyinvbjsfeaj",
+ "name": "Teste",
"host": "comerciode188007.fluig.cloudtotvs.com.br",
"ssl": true,
"port": 443,
"username": "andrey.cunha",
- "password": "eyJpdiI6ImRjNGY4YzFkZmNiM2FhNDJiMGE3NDlmYjI5YjFkZjBhIiwic2FsdCI6IjU2MzUzZTcxOGZjZGRjZmUwZDI4MWYxZTllOWFlMDM3IiwidGV4dCI6IjU1NWQxZTE3YzUwYTQwYjNjMzAwYTc3M2VmNWQwODU1In0=",
+ "password": "eyJpdiI6ImNlN2IyOTIzNjljNDZmZDQwMTM5Njg2MTEyNjNlM2IyIiwic2FsdCI6ImM1ZDFjYzhiMTFiZGNjNDBhOTQzMGUwZGU0OWY5NmZmIiwidGV4dCI6ImY4M2FmZTUzNTkzYTBjNDc2OTQ3NDQ4NDc0ZGVlNmRiIn0=",
"userCode": "andrey.cunha",
"confirmExporting": false,
"hasBrowser": false,
diff --git a/Transferência Ginseng/datasets/ds_fiscal_invoice_by_keys.js b/Transferência Ginseng/datasets/ds_fiscal_invoice_by_keys.js
new file mode 100644
index 0000000..ad4ffc2
--- /dev/null
+++ b/Transferência Ginseng/datasets/ds_fiscal_invoice_by_keys.js
@@ -0,0 +1,428 @@
+function defineStructure() {
+ addColumn("success");
+ addColumn("message");
+ addColumn("key");
+ addColumn("invoiceNumber");
+ addColumn("serie");
+ addColumn("emissionDate");
+ addColumn("operationDate");
+ addColumn("supplierName");
+ addColumn("documentValue");
+ addColumn("totalItemsValue");
+ addColumn("situation");
+ addColumn("fiscalOperationDescription");
+ addColumn("itemCount");
+ addColumn("itensJson");
+ addColumn("storeId");
+ addColumn("invoiceId");
+ addColumn("emitterEmployeeId");
+ addColumn("updatedAt");
+}
+
+function onSync(lastSyncDate) {}
+
+function createDataset(fields, constraints, sortFields) {
+ var dataset = DatasetBuilder.newDataset();
+ addDefaultColumns(dataset);
+
+ try {
+ var key = normalizeDigits(getConstraintValue(constraints, "key"));
+ if (!key) {
+ addErrorRow(dataset, "Informe a chave da NFe.");
+ return dataset;
+ }
+
+ if (!/^\d{44}$/.test(key)) {
+ addErrorRow(dataset, "A chave da NFe deve conter 44 digitos.");
+ return dataset;
+ }
+
+ var auth = resolveAuth(constraints);
+ var diagnostics = [];
+
+ var endpoints = [
+ "/fiscal-invoices?key=" + key,
+ "fiscal-invoices?key=" + key,
+ "/fiscal/invoices?key=" + key,
+ "/fiscal/invoice?key=" + key,
+ "/invoice?key=" + key
+ ];
+
+ var apiObj = null;
+ var hitInfo = "";
+ var lastApiMessage = "";
+
+ try {
+ var clientService = fluigAPI.getAuthorizeClientService();
+ for (var i = 0; i < endpoints.length; i++) {
+ var endpoint = endpoints[i];
+ var resp = invokeAuthorizedGet(clientService, endpoint, auth);
+ diagnostics.push(endpoint + " => HTTP " + trim(resp.status));
+ var parsed = parseApiPayload(resp.body);
+ if (parsed && trim(parsed.message)) {
+ lastApiMessage = trim(parsed.message);
+ }
+ if (String(resp.status) === "200" && isApiSuccess(parsed)) {
+ apiObj = parsed;
+ hitInfo = endpoint;
+ break;
+ }
+ }
+ } catch (eService) {
+ diagnostics.push("authorizeClientService exception: " + eService);
+ }
+
+ if (!apiObj) {
+ var directUrls = [
+ "https://api.grupoginseng.com.br/fiscal-invoices?key=" + key,
+ "https://api.grupoginseng.com.br/fiscal/invoice?key=" + key
+ ];
+
+ for (var d = 0; d < directUrls.length; d++) {
+ var url = directUrls[d];
+ var directResp = fetchDirect(url, 30000, auth);
+ diagnostics.push(url + " => HTTP " + trim(directResp.status));
+ var parsedDirect = parseApiPayload(directResp.body);
+ if (parsedDirect && trim(parsedDirect.message)) {
+ lastApiMessage = trim(parsedDirect.message);
+ }
+ if (String(directResp.status) === "200" && isApiSuccess(parsedDirect)) {
+ apiObj = parsedDirect;
+ hitInfo = url;
+ break;
+ }
+ }
+ }
+
+ if (!apiObj) {
+ var msg = "Falha ao consultar API da NFe. Tentativas: " + diagnostics.join(" | ");
+ if (lastApiMessage) {
+ msg += " | Ultima mensagem da API: " + lastApiMessage;
+ }
+ addErrorRow(dataset, msg);
+ return dataset;
+ }
+
+ if (!apiObj.success || !apiObj.data) {
+ addErrorRow(dataset, trim(apiObj.message) || "NFe nao encontrada. Fonte: " + hitInfo);
+ return dataset;
+ }
+
+ var dataNfe = apiObj.data || {};
+ var itens = dataNfe.itens || [];
+ var itensJson = JSON.stringify(buildNfeItems(itens));
+
+ dataset.addRow([
+ "true",
+ "OK (" + hitInfo + ")",
+ trim(dataNfe.key),
+ trim(dataNfe.invoiceNumber),
+ trim(dataNfe.serie),
+ formatIsoDate(dataNfe.emissionDate),
+ formatIsoDate(dataNfe.operationDate),
+ trim(dataNfe.supplierName),
+ trim(dataNfe.documentValue),
+ trim(dataNfe.totalItemsValue),
+ trim(dataNfe.situation),
+ trim(dataNfe.fiscalOperationDescription),
+ String(itens.length),
+ itensJson,
+ trim(dataNfe.storeId),
+ trim(dataNfe.invoiceId),
+ trim(dataNfe.emitterEmployeeId),
+ formatIsoDateTime(dataNfe.updatedAt)
+ ]);
+ } catch (e) {
+ addErrorRow(dataset, "Erro ao consultar a NFe: " + e);
+ }
+
+ return dataset;
+}
+
+function onMobileSync(user) {}
+
+function addDefaultColumns(dataset) {
+ dataset.addColumn("success");
+ dataset.addColumn("message");
+ dataset.addColumn("key");
+ dataset.addColumn("invoiceNumber");
+ dataset.addColumn("serie");
+ dataset.addColumn("emissionDate");
+ dataset.addColumn("operationDate");
+ dataset.addColumn("supplierName");
+ dataset.addColumn("documentValue");
+ dataset.addColumn("totalItemsValue");
+ dataset.addColumn("situation");
+ dataset.addColumn("fiscalOperationDescription");
+ dataset.addColumn("itemCount");
+ dataset.addColumn("itensJson");
+ dataset.addColumn("storeId");
+ dataset.addColumn("invoiceId");
+ dataset.addColumn("emitterEmployeeId");
+ dataset.addColumn("updatedAt");
+}
+
+function addErrorRow(dataset, message) {
+ dataset.addRow([
+ "false",
+ String(message || "Erro ao consultar NFe."),
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "0",
+ "[]",
+ "",
+ "",
+ "",
+ ""
+ ]);
+}
+
+function getConstraintValue(constraints, fieldName) {
+ if (!constraints || !fieldName) return "";
+
+ for (var i = 0; i < constraints.length; i++) {
+ var c = constraints[i];
+ if (!c || !c.fieldName) continue;
+ if (String(c.fieldName) === String(fieldName)) {
+ return c.initialValue;
+ }
+ }
+ return "";
+}
+
+function resolveAuth(constraints) {
+ var token = trim(getConstraintValue(constraints, "token"));
+ if (!token) {
+ try {
+ token = trim(java.lang.System.getenv("GINSENG_FISCAL_TOKEN"));
+ } catch (e1) {}
+ }
+ if (!token) {
+ // fallback informado durante homologacao
+ token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhcGlnaW5zZW5nIiwiZXhwIjoxNzg3NDQ4MDY3fQ.GJqcIJBkMIfp_q_KRzgGuAHWWo93j3FWo3TObKqlAwA";
+ }
+
+ var basicUser = trim(getConstraintValue(constraints, "basicUser"));
+ var basicPass = trim(getConstraintValue(constraints, "basicPass"));
+
+ // Fallback operacional para homologacao, conforme credenciais validadas em teste manual.
+ if (!basicUser) basicUser = "fluig";
+ if (!basicPass) basicPass = "Ginseng@";
+
+ return {
+ token: token,
+ basicUser: basicUser,
+ basicPass: basicPass
+ };
+}
+
+function invokeAuthorizedGet(clientService, endpoint, auth) {
+ var authHeader = resolveAuthHeader(auth);
+ var headers = { "Accept": "application/json" };
+ if (authHeader) {
+ headers.Authorization = authHeader;
+ if (auth && auth.token) {
+ headers["x-access-token"] = auth.token;
+ }
+ }
+
+ var data = {
+ companyId: String(getValue("WKCompany") || "1"),
+ serviceCode: "GINSENG APITESTE",
+ endpoint: endpoint,
+ method: "get",
+ timeoutService: "30000",
+ params: {},
+ headers: headers
+ };
+
+ var vo = clientService.invoke(JSON.stringify(data));
+ return {
+ status: vo ? String(vo.getHttpStatusResult() || "") : "",
+ body: vo ? String(vo.getResult() || "") : ""
+ };
+}
+
+function parseApiPayload(bodyText) {
+ var raw = trim(bodyText);
+ if (!raw) return null;
+
+ var obj = parseJsonSafe(raw);
+ if (!obj) return null;
+
+ if (typeof obj.success !== "undefined" || typeof obj.data !== "undefined") {
+ return obj;
+ }
+
+ if (obj.content) {
+ if (typeof obj.content === "string") {
+ var c = parseJsonSafe(obj.content);
+ if (c) return c;
+ } else {
+ return obj.content;
+ }
+ }
+
+ if (obj.result) {
+ if (typeof obj.result === "string") {
+ var r = parseJsonSafe(obj.result);
+ if (r) return r;
+ } else {
+ return obj.result;
+ }
+ }
+
+ return obj;
+}
+
+function isApiSuccess(obj) {
+ if (!obj || !obj.data) return false;
+ if (obj.success === true) return true;
+ if (String(obj.success).toLowerCase() === "true") return true;
+ return false;
+}
+
+function fetchDirect(url, timeoutMs, auth) {
+ var conn = null;
+ var reader = null;
+ try {
+ var URL = java.net.URL;
+ var InputStreamReader = java.io.InputStreamReader;
+ var BufferedReader = java.io.BufferedReader;
+ var StringBuilder = java.lang.StringBuilder;
+
+ conn = new URL(url).openConnection();
+ conn.setRequestMethod("GET");
+ conn.setConnectTimeout(timeoutMs || 30000);
+ conn.setReadTimeout(timeoutMs || 30000);
+ conn.setRequestProperty("Accept", "application/json");
+
+ var authHeader = resolveAuthHeader(auth);
+ if (authHeader) {
+ conn.setRequestProperty("Authorization", authHeader);
+ if (auth.token) conn.setRequestProperty("x-access-token", auth.token);
+ }
+
+ var status = conn.getResponseCode();
+ var stream = (status >= 200 && status < 300) ? conn.getInputStream() : conn.getErrorStream();
+ if (stream == null) return { status: status, body: "" };
+
+ reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
+ var sb = new StringBuilder();
+ var line = null;
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+
+ return { status: String(status), body: String(sb.toString()) };
+ } catch (e) {
+ return { status: "", body: "" };
+ } finally {
+ try { if (reader) reader.close(); } catch (e1) {}
+ try { if (conn) conn.disconnect(); } catch (e2) {}
+ }
+}
+
+function resolveAuthHeader(auth) {
+ auth = auth || {};
+ if (auth.basicUser && auth.basicPass) {
+ var raw = String(auth.basicUser) + ":" + String(auth.basicPass);
+ var bytes = new java.lang.String(raw).getBytes("UTF-8");
+ var encoded = java.util.Base64.getEncoder().encodeToString(bytes);
+ return "Basic " + String(encoded);
+ }
+ if (auth.token) {
+ return "Bearer " + String(auth.token);
+ }
+ return "";
+}
+
+function buildNfeItems(items) {
+ var out = [];
+ if (!items || !(items instanceof Array)) return out;
+
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i] || {};
+ out.push({
+ productId: trim(item.productId),
+ quantity: toNumber(item.quantity || item.completeQuantity),
+ code: trim(item.code || item.sku || item.productCode || item.codigo)
+ });
+ }
+
+ return out;
+}
+
+function toNumber(value) {
+ var text = trim(value).replace(",", ".");
+ var n = parseFloat(text);
+ return isNaN(n) ? 0 : n;
+}
+
+function normalizeDigits(value) {
+ return String(value == null ? "" : value).replace(/\D/g, "");
+}
+
+function parseJsonSafe(text) {
+ try {
+ return JSON.parse(text);
+ } catch (e) {
+ return null;
+ }
+}
+
+function trim(value) {
+ return String(value == null ? "" : value).trim();
+}
+
+function formatIsoDate(value) {
+ var text = trim(value);
+ if (!text) return "";
+
+ try {
+ var datePart = text.split("T")[0].split("-");
+ if (datePart.length !== 3) {
+ return text;
+ }
+ return datePart[2] + "/" + datePart[1] + "/" + datePart[0];
+ } catch (e) {
+ return text;
+ }
+}
+
+function formatIsoDateTime(value) {
+ var text = trim(value);
+ if (!text) return "";
+
+ try {
+ var dt = text.split("T");
+ if (dt.length < 1) return text;
+
+ var datePart = dt[0].split("-");
+ if (datePart.length !== 3) return text;
+
+ var timePart = "";
+ if (dt.length > 1) {
+ timePart = dt[1].replace("Z", "");
+ var dotIndex = timePart.indexOf(".");
+ if (dotIndex >= 0) {
+ timePart = timePart.substring(0, dotIndex);
+ }
+ }
+
+ var dateStr = datePart[2] + "/" + datePart[1] + "/" + datePart[0];
+ if (!timePart) return dateStr;
+
+ return dateStr + " " + timePart;
+ } catch (e) {
+ return text;
+ }
+}
diff --git a/Transferência Ginseng/datasets/ds_motoristas_grupo.js b/Transferência Ginseng/datasets/ds_motoristas_grupo.js
new file mode 100644
index 0000000..4af247b
--- /dev/null
+++ b/Transferência Ginseng/datasets/ds_motoristas_grupo.js
@@ -0,0 +1,301 @@
+function defineStructure() {
+ addColumn("LOGIN");
+ addColumn("NOME");
+ addColumn("EMAIL");
+ addColumn("COLLEAGUE_ID");
+ addColumn("GROUP_ID");
+}
+
+function onSync(lastSyncDate) {}
+function onMobileSync(user) {}
+
+function createDataset(fields, constraints, sortFields) {
+ var dataset = DatasetBuilder.newDataset();
+ dataset.addColumn("LOGIN");
+ dataset.addColumn("NOME");
+ dataset.addColumn("EMAIL");
+ dataset.addColumn("COLLEAGUE_ID");
+ dataset.addColumn("GROUP_ID");
+
+ try {
+ var cfg = parseConstraints(constraints);
+ var members = getMembersFromGroup(cfg.groupId);
+ var termo = normalize(cfg.termoLivre);
+ var added = 0;
+
+ for (var i = 0; i < members.length; i++) {
+ var memberId = trim(members[i]);
+ if (!memberId) continue;
+
+ var col = getColleagueById(memberId);
+ if (!col) continue;
+
+ if (termo) {
+ var blob = normalize([
+ col.LOGIN,
+ col.NOME,
+ col.EMAIL,
+ col.COLLEAGUE_ID
+ ].join(" "));
+ if (blob.indexOf(termo) === -1) {
+ continue;
+ }
+ }
+
+ dataset.addRow([
+ col.LOGIN,
+ col.NOME,
+ col.EMAIL,
+ col.COLLEAGUE_ID,
+ cfg.groupId
+ ]);
+ added++;
+ }
+
+ if (added === 0) {
+ // Mantem dataset vazio para o zoom nao exibir usuarios fora do grupo.
+ }
+ } catch (e) {
+ safeLogError("[ds_motoristas_grupo] Erro no createDataset: " + e);
+ dataset = DatasetBuilder.newDataset();
+ dataset.addColumn("LOGIN");
+ dataset.addColumn("NOME");
+ dataset.addColumn("EMAIL");
+ dataset.addColumn("COLLEAGUE_ID");
+ dataset.addColumn("GROUP_ID");
+ }
+
+ return dataset;
+}
+
+function parseConstraints(constraints) {
+ var out = {
+ groupId: "Motoristas",
+ termoLivre: ""
+ };
+
+ if (!constraints) return out;
+
+ for (var i = 0; i < constraints.length; i++) {
+ var c = constraints[i];
+ if (!c) continue;
+
+ var field = getConstraintFieldName(c);
+ var value = getConstraintInitialValue(c);
+ if (!field) continue;
+ if (!value) continue;
+
+ if (
+ field === "GROUP_ID" ||
+ field === "groupId" ||
+ field === "group_id" ||
+ field === "colleagueGroupPK.groupId"
+ ) {
+ out.groupId = value;
+ continue;
+ }
+
+ if (
+ field !== "metadata#id" &&
+ field !== "metadata#active" &&
+ field !== "sqlLimit"
+ ) {
+ var cleaned = cleanSearchValue(value);
+ if (cleaned && (!out.termoLivre || cleaned.length > out.termoLivre.length)) {
+ out.termoLivre = cleaned;
+ }
+ }
+ }
+
+ return out;
+}
+
+function getMembersFromGroup(groupId) {
+ var members = {};
+ var out = [];
+ var gId = trim(groupId);
+ if (!gId) return out;
+
+ var fieldOptions = [
+ "colleagueGroupPK.groupId",
+ "groupId",
+ "group"
+ ];
+
+ var groupCandidates = [gId];
+ var upper = gId.toUpperCase();
+ var lower = gId.toLowerCase();
+ if (groupCandidates.indexOf(upper) < 0) groupCandidates.push(upper);
+ if (groupCandidates.indexOf(lower) < 0) groupCandidates.push(lower);
+
+ var ds = null;
+ for (var g = 0; g < groupCandidates.length; g++) {
+ for (var i = 0; i < fieldOptions.length; i++) {
+ try {
+ var cGroup = DatasetFactory.createConstraint(fieldOptions[i], groupCandidates[g], groupCandidates[g], ConstraintType.MUST);
+ ds = DatasetFactory.getDataset("colleagueGroup", null, [cGroup], null);
+ if (ds && ds.rowsCount > 0) {
+ break;
+ }
+ } catch (e) {
+ safeLogError("[ds_motoristas_grupo] Erro consultando colleagueGroup (" + fieldOptions[i] + "=" + groupCandidates[g] + "): " + e);
+ ds = null;
+ }
+ }
+ if (ds && ds.rowsCount > 0) {
+ break;
+ }
+ }
+
+ if (!ds || ds.rowsCount === 0) {
+ // Fallback: alguns ambientes permitem filtrar direto no dataset colleague por groupId.
+ try {
+ var cGroupCol = DatasetFactory.createConstraint("groupId", gId, gId, ConstraintType.MUST);
+ ds = DatasetFactory.getDataset("colleague", null, [cGroupCol], null);
+ if (ds && ds.rowsCount > 0) {
+ for (var x = 0; x < ds.rowsCount; x++) {
+ var fallbackId = trim(
+ ds.getValue(x, "colleaguePK.colleagueId") ||
+ ds.getValue(x, "colleagueId") ||
+ ds.getValue(x, "login")
+ );
+ if (!fallbackId) continue;
+ if (members[fallbackId]) continue;
+ members[fallbackId] = true;
+ out.push(fallbackId);
+ }
+ }
+ } catch (eFallback) {
+ safeLogError("[ds_motoristas_grupo] Erro no fallback por groupId no colleague: " + eFallback);
+ }
+ return out;
+ }
+
+ for (var r = 0; r < ds.rowsCount; r++) {
+ var colleagueId = trim(
+ ds.getValue(r, "colleagueGroupPK.colleagueId") ||
+ ds.getValue(r, "colleagueId") ||
+ ds.getValue(r, "login")
+ );
+ if (!colleagueId) continue;
+ if (members[colleagueId]) continue;
+ members[colleagueId] = true;
+ out.push(colleagueId);
+ }
+
+ return out;
+}
+
+function getColleagueById(colleagueId) {
+ var id = trim(colleagueId);
+ if (!id) return null;
+
+ var fieldsToTry = ["colleaguePK.colleagueId", "colleagueId", "login"];
+ var ds = null;
+
+ // 1) Tenta buscando somente ativos com diferentes campos.
+ for (var i = 0; i < fieldsToTry.length; i++) {
+ ds = getColleagueDataset(id, fieldsToTry[i], true);
+ if (ds && ds.rowsCount > 0) {
+ break;
+ }
+ }
+
+ // 2) Fallback sem constraint de ativo (alguns ambientes tratam "active" de forma diferente).
+ if (!ds || ds.rowsCount === 0) {
+ for (var j = 0; j < fieldsToTry.length; j++) {
+ ds = getColleagueDataset(id, fieldsToTry[j], false);
+ if (ds && ds.rowsCount > 0) {
+ break;
+ }
+ }
+ }
+
+ if (!ds || ds.rowsCount === 0) return null;
+
+ var row = pickActiveRow(ds);
+ if (row < 0) row = 0;
+
+ var colleaguePkId = trim(
+ ds.getValue(row, "colleaguePK.colleagueId") ||
+ ds.getValue(row, "colleagueId") ||
+ ds.getValue(row, "login")
+ );
+ if (!colleaguePkId) return null;
+
+ return {
+ LOGIN: trim(ds.getValue(row, "login")),
+ NOME: trim(ds.getValue(row, "colleagueName")),
+ EMAIL: trim(ds.getValue(row, "mail")),
+ COLLEAGUE_ID: colleaguePkId
+ };
+}
+
+function getColleagueDataset(id, fieldName, onlyActive) {
+ try {
+ var constraints = [
+ DatasetFactory.createConstraint(fieldName, id, id, ConstraintType.MUST)
+ ];
+
+ if (onlyActive) {
+ constraints.push(DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST));
+ }
+
+ return DatasetFactory.getDataset("colleague", null, constraints, null);
+ } catch (e) {
+ safeLogError("[ds_motoristas_grupo] Erro consultando colleague (" + fieldName + "=" + id + ", active=" + onlyActive + "): " + e);
+ return null;
+ }
+}
+
+function pickActiveRow(ds) {
+ if (!ds || ds.rowsCount <= 0) return -1;
+
+ for (var i = 0; i < ds.rowsCount; i++) {
+ var activeValue = trim(ds.getValue(i, "active") || ds.getValue(i, "colleaguePK.active"));
+ if (!activeValue) return i;
+
+ var n = normalize(activeValue);
+ if (n === "true" || n === "1" || n === "yes" || n === "sim" || n === "y" || n === "s" || n === "t") {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+function getConstraintFieldName(constraint) {
+ try {
+ if (constraint.fieldName) return String(constraint.fieldName);
+ if (constraint._field) return String(constraint._field);
+ if (typeof constraint.getFieldName === "function") return String(constraint.getFieldName());
+ } catch (e) {}
+ return "";
+}
+
+function getConstraintInitialValue(constraint) {
+ try {
+ if (constraint.initialValue != null) return trim(constraint.initialValue);
+ if (constraint._initialValue != null) return trim(constraint._initialValue);
+ if (typeof constraint.getInitialValue === "function") return trim(constraint.getInitialValue());
+ } catch (e) {}
+ return "";
+}
+
+function trim(v) {
+ return String(v == null ? "" : v).trim();
+}
+
+function normalize(v) {
+ return trim(v).toLowerCase();
+}
+
+function cleanSearchValue(v) {
+ return trim(v).replace(/[%*_]/g, "");
+}
+
+function safeLogError(message) {
+ try {
+ log.error(String(message));
+ } catch (e) {}
+}
diff --git a/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/events/validateForm.js b/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/events/validateForm.js
index 8367d3a..9c04ff5 100644
--- a/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/events/validateForm.js
+++ b/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/events/validateForm.js
@@ -13,61 +13,91 @@ function validateForm(form) {
switch (atividade) {
case EMISSAO:
-
- // log.info("Abertura de Chamado CAERN - Área do Solicitante: " + form.getValue("areaSolicitante"));
- // if (form.getValue("areaSolicitante") == "") {
- // message += getMessage("Área do Solicitante", 2, form);
- // hasErros = true;
- // }
-
- log.info("Por favor, anexar a nota fiscal" + form.getValue("fnAnexo_Nfe"));
- if (form.getValue("fnAnexo_Nfe") == "") {
- message += getMessage("Nota Fiscal", 3, form);
+ log.info("Validando rastreabilidade da emissao da NFe");
+ var chaveNfe = String(form.getValue("chaveNfe") || "").replace(/\D/g, "");
+ if (chaveNfe == "") {
+ message += getMessage("Chave de acesso da NFe", 1, form);
hasErros = true;
}
-
- // var tabelaAnexos = form.getChildrenIndexes("tabelaAnexoOcorrencia")
-
- // if (tabelaAnexos.length > 0) {
-
- // for (var i = 0; i < tabelaAnexos.length; i++) {
-
- // if (form.getValue("fnAnexoOcorrencia" + "" + tabelaAnexos[i]) == null || form.getValue("fnAnexoOcorrencia" + "" + tabelaAnexos[i]) == "") {
- // message += getMessage("Anexo " + tabelaAnexos[i], 1, form)
- // hasErros = true;
- // }
-
- // }
-
- // } else {
-
- // message += getMessage("A tabela de Anexos esta vazia", 0, form)
- // hasErros = true;
-
- // }
-
- break;
-
+ if (chaveNfe != "" && chaveNfe.length != 44) {
+ message += "Campo \"Chave de acesso da NFe\" deve conter 44 digitos.
";
+ hasErros = true;
+ }
+ if (form.getValue("invoiceIdNfeConsulta") == "") {
+ message += "Consulte a chave da NFe antes de enviar esta etapa.
";
+ hasErros = true;
+ }
+ var qtdDivergenciasNfe = parseInt(String(form.getValue("qtdDivergenciasNfe") || "0"), 10);
+ if (!isNaN(qtdDivergenciasNfe) && qtdDivergenciasNfe > 0) {
+ message += "Existem " + qtdDivergenciasNfe + " divergencia(s) entre a solicitacao e a NFe.
";
+ hasErros = true;
+ }
+ if (form.getValue("usuarioEmissorNfe") == "") {
+ message += getMessage("Usuário emissor da NFe", 1, form);
+ hasErros = true;
+ }
+ if (form.getValue("dataEmissaoNfe") == "") {
+ message += getMessage("Data da emissão", 1, form);
+ hasErros = true;
+ }
+ break;
+
case COLETA:
- log.info("Por favor, registre o momento da coleta" + form.getValue("fdAnexo_Coleta"));
- if (form.getValue("fdAnexo_Coleta") == "") {
- message += getMessage("Coleta", 3, form);
- hasErros = true;
- }
+ log.info("Validando dados da coleta");
+ if (form.getValue("motoristaColetaNome") == "") {
+ message += getMessage("Motorista responsável pela coleta", 1, form);
+ hasErros = true;
+ }
+ if (form.getValue("dataColeta") == "") {
+ message += getMessage("Data da coleta", 1, form);
+ hasErros = true;
+ }
+ var tipoMotoristaEntregaColeta = String(form.getValue("tipoMotoristaEntrega") || "");
+ if (tipoMotoristaEntregaColeta == "") {
+ message += getMessage("Quem vai fazer a entrega", 2, form);
+ hasErros = true;
+ }
+ if (tipoMotoristaEntregaColeta == "outro" && form.getValue("motoristaEntregaLogin") == "") {
+ message += getMessage("Selecionar outro motorista", 1, form);
+ hasErros = true;
+ }
+ if (tipoMotoristaEntregaColeta == "mesmo" && form.getValue("motoristaColetaLogin") == "") {
+ message += getMessage("Login do motorista da coleta", 1, form);
+ hasErros = true;
+ }
+ break;
case ENTREGA:
- log.info("Por favor, registre o momento da entrega" + form.getValue("fdAnexo_Entrega"));
- if (form.getValue("fdAnexo_Entrega") == "") {
- message += getMessage("Entrega", 3, form);
- hasErros = true;
- }
+ log.info("Validando dados da entrega");
+ if (form.getValue("motoristaEntregaLogin") == "") {
+ message += getMessage("Motorista da entrega definido na coleta", 1, form);
+ hasErros = true;
+ }
+ if (form.getValue("motoristaEntregaNome") == "") {
+ message += getMessage("Motorista responsável pela entrega", 1, form);
+ hasErros = true;
+ }
+ if (form.getValue("dataEntrega") == "") {
+ message += getMessage("Data da entrega", 1, form);
+ hasErros = true;
+ }
+ break;
case RECEBIMENTO:
- log.info("Por favor, registre o recebimento do material" + form.getValue("fdAnexo_recebimento"));
- if (form.getValue("fdAnexo_recebimento") == "") {
- message += getMessage("Recebimento", 3, form);
- hasErros = true;
- }
+ log.info("Validando recebimento e conferencia dos itens");
+ var validacaoItens = String(form.getValue("validacaoItens") || "");
+ if (validacaoItens == "") {
+ message += getMessage("Validação do recebimento", 2, form);
+ hasErros = true;
+ }
+ if (
+ (validacaoItens == "divergencia" || validacaoItens == "naoEntregue" || validacaoItens == "incorreto") &&
+ form.getValue("justificativaDecisaoItens") == ""
+ ) {
+ message += getMessage("Descreva a divergência encontrada", 1, form);
+ hasErros = true;
+ }
+ break;
default:
break;
}
@@ -99,4 +129,5 @@ function getMessage(texto, tipo, form) {
} else {
return 'A quantidade existente de campos "' + texto + '" deve ser maior do que 0.'
}
-}
\ No newline at end of file
+}
+
diff --git a/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/excel.js b/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/excel.js
index 4645a51..e1d8155 100644
--- a/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/excel.js
+++ b/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/excel.js
@@ -1,41 +1,102 @@
+var xlsxLoader = {
+ loading: false,
+ callbacks: []
+};
+
function carregarItensDoExcel(fileInputId) {
- const fileInput = document.getElementById(fileInputId);
- const file = fileInput ? fileInput.files[0] : null;
+ var fileInput = document.getElementById(fileInputId);
+ var file = fileInput ? fileInput.files[0] : null;
if (!file) {
FLUIGC.toast({ title: 'Erro', message: 'Nenhum arquivo selecionado.', type: 'danger' });
return;
}
- if (typeof XLSX === "undefined") {
- FLUIGC.toast({ title: 'Erro', message: 'Biblioteca XLSX nao carregada.', type: 'danger' });
+
+ showExcelLoading();
+ ensureXlsxLibrary(function (err) {
+ if (err) {
+ hideExcelLoading();
+ FLUIGC.toast({ title: 'Erro', message: 'Biblioteca XLSX indisponivel.', type: 'danger' });
+ console.error("Erro ao carregar XLSX:", err);
+ return;
+ }
+
+ processarArquivoExcel(file);
+ });
+}
+
+function ensureXlsxLibrary(callback) {
+ if (typeof XLSX !== "undefined") {
+ callback();
return;
}
- showExcelLoading();
+ xlsxLoader.callbacks.push(callback);
+ if (xlsxLoader.loading) {
+ return;
+ }
- const reader = new FileReader();
+ xlsxLoader.loading = true;
+ loadXlsxScript(0);
+}
+
+function loadXlsxScript(index) {
+ var urls = [
+ "/portal/resources/js/xlsx.full.min.js",
+ "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"
+ ];
+
+ if (index >= urls.length) {
+ flushXlsxCallbacks(new Error("Biblioteca XLSX nao encontrada."));
+ return;
+ }
+
+ $.getScript(urls[index])
+ .done(function () {
+ if (typeof XLSX === "undefined") {
+ loadXlsxScript(index + 1);
+ return;
+ }
+ flushXlsxCallbacks();
+ })
+ .fail(function () {
+ loadXlsxScript(index + 1);
+ });
+}
+
+function flushXlsxCallbacks(err) {
+ var callbacks = xlsxLoader.callbacks.splice(0, xlsxLoader.callbacks.length);
+ xlsxLoader.loading = false;
+
+ for (var i = 0; i < callbacks.length; i++) {
+ callbacks[i](err);
+ }
+}
+
+function processarArquivoExcel(file) {
+ var reader = new FileReader();
reader.onload = function (e) {
// Permite o navegador renderizar o overlay antes de processar.
setTimeout(function () {
try {
- const data = new Uint8Array(e.target.result);
- const workbook = XLSX.read(data, { type: 'array' });
- const sheetName = workbook.SheetNames[0];
- const sheet = workbook.Sheets[sheetName];
- const linhas = XLSX.utils.sheet_to_json(sheet, { defval: "" });
+ var data = new Uint8Array(e.target.result);
+ var workbook = XLSX.read(data, { type: 'array' });
+ var sheetName = workbook.SheetNames[0];
+ var sheet = workbook.Sheets[sheetName];
+ var linhas = XLSX.utils.sheet_to_json(sheet, { defval: "" });
// Limpa a tabela (sem usar form)
- const indices = $("input[id^='codigoItem___']").map(function () {
+ var indices = $("input[id^='codigoItem___']").map(function () {
return $(this).attr("id").split("___")[1];
}).get();
$.each(indices, function (_, idx) {
fnWdkRemoveChild(idx);
});
- const linhasValidas = [];
+ var linhasValidas = [];
$.each(linhas, function (_, item) {
- const codigo = getCellByAliases(item, ["codigoItem", "codigo", "codItem", "sku", "code", "item"]);
- const quantidade = getCellByAliases(item, ["quantidadeItem", "quantidade", "qtd", "qtde"]);
- const descricao = getCellByAliases(item, ["descricao", "description", "desc"]);
+ var codigo = getCellByAliases(item, ["codigoItem", "codigo", "codItem", "sku", "code", "item"]);
+ var quantidade = getCellByAliases(item, ["quantidadeItem", "quantidade", "qtd", "qtde"]);
+ var descricao = getCellByAliases(item, ["descricao", "description", "desc"]);
if (!codigo || !quantidade) {
return;
@@ -59,23 +120,33 @@ function carregarItensDoExcel(fileInputId) {
// Adiciona os itens da planilha
$.each(linhasValidas, function (_, item) {
- const idx = wdkAddChild('tabelaItens');
- const zoomObj = window[`descricao___${idx}`];
+ var idx = wdkAddChild('tabelaItens');
+ var zoomObj = window["descricao___" + idx];
if (zoomObj && typeof zoomObj.setValue === "function") {
zoomObj.setValue(item.codigo);
} else {
// Fallback visual caso o objeto zoom ainda nao esteja pronto no momento.
- $(`#descricao___${idx}`).val(item.codigo);
+ $("#descricao___" + idx).val(item.codigo);
}
- $(`#quantidadeItem___${idx}`).val(item.quantidade);
+ $("#quantidadeItem___" + idx).val(item.quantidade);
+ $("#codigoProdutoItem___" + idx).val(item.codigo);
- var descricaoFinal = item.descricao || buscarDescricaoProduto(item.codigo);
+ var produtoInfo = buscarProdutoPorCodigo(item.codigo);
+ if (produtoInfo.id) {
+ $("#productIdItem___" + idx).val(produtoInfo.id);
+ }
+
+ var descricaoFinal = item.descricao || produtoInfo.descricao;
if (descricaoFinal) {
- $(`#codigoItem___${idx}`).val(descricaoFinal);
+ $("#codigoItem___" + idx).val(descricaoFinal);
}
});
+ if (typeof processarConferenciaNfe === "function") {
+ processarConferenciaNfe();
+ }
+
FLUIGC.toast({ title: 'Sucesso', message: linhasValidas.length + ' itens carregados com sucesso!', type: 'success' });
} catch (err) {
FLUIGC.toast({ title: 'Erro', message: 'Falha ao processar Excel: ' + err.message, type: 'danger' });
@@ -118,36 +189,46 @@ function normalizeHeader(text) {
.toLowerCase();
}
-function buscarDescricaoProduto(codigo) {
+function buscarProdutoPorCodigo(codigo) {
try {
if (typeof DatasetFactory === "undefined" || typeof ConstraintType === "undefined") {
- return "";
+ return { descricao: "", id: "" };
}
var codigoTxt = String(codigo || "").trim();
- if (!codigoTxt) return "";
+ if (!codigoTxt) return { descricao: "", id: "" };
var cCodigo = DatasetFactory.createConstraint("Code", codigoTxt, codigoTxt, ConstraintType.MUST);
var ds = DatasetFactory.getDataset("ds_rgb_products", null, [cCodigo], null);
if (!ds || !ds.values || !ds.values.length) {
- return "";
+ return { descricao: "", id: "" };
}
for (var i = 0; i < ds.values.length; i++) {
var row = ds.values[i] || {};
if (String(row.Code || "").trim() === codigoTxt) {
- return String(row.descricao || row.Description || "").trim();
+ return {
+ descricao: String(row.descricao || row.Description || "").trim(),
+ id: String(row.id || "").trim()
+ };
}
}
var first = ds.values[0] || {};
- return String(first.descricao || first.Description || "").trim();
+ return {
+ descricao: String(first.descricao || first.Description || "").trim(),
+ id: String(first.id || "").trim()
+ };
} catch (e) {
console.error("Erro ao buscar descricao por codigo:", e);
- return "";
+ return { descricao: "", id: "" };
}
}
+function buscarDescricaoProduto(codigo) {
+ return buscarProdutoPorCodigo(codigo).descricao;
+}
+
function showExcelLoading() {
var overlay = document.getElementById("excelLoadingOverlay");
if (overlay) {
diff --git a/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/script.js b/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/script.js
index ab886ab..519e775 100644
--- a/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/script.js
+++ b/Transferência Ginseng/forms/totvsflow_solicitacao_transferencia/script.js
@@ -26,13 +26,41 @@ $(document).ready(function () {
$('#btnRemoverExcel').hide();
});
+ $('#chaveNfe').on('input', function () {
+ var key = normalizeNfeKey($(this).val());
+ $(this).val(key);
+ clearNfeConsultaFields();
+ setNfeFeedback("", "hidden");
+ });
+
+ $('#btnConsultarChaveNfe').on('click', function () {
+ consultarChaveNfe();
+ });
+
+ $(document).on("change", "input[name='tipoMotoristaEntrega']", function () {
+ applyMotoristaEntregaMode($(this).val(), false);
+ });
+
+ $(document).on("change", "#motoristaEntregaSelecionado", function () {
+ applySelectedMotoristaEntregaOption();
+ });
+
+ $(document).on("input", "input[name^='quantidadeItem___']", function () {
+ processarConferenciaNfe();
+ });
+
if ($("#formMode").val() == "VIEW") {
showAndBlock(["all"]);
+ $("#btnConsultarChaveNfe").prop("disabled", true).hide();
} else {
//show the right fields
var activity = $("#activity").val();
var requestDate = getCurrentDate();
+ if (String(activity) !== "6") {
+ $("#btnConsultarChaveNfe").prop("disabled", true).hide();
+ }
+
$(".activity").hide();
$(".activity-" + activity).show();
@@ -51,10 +79,14 @@ $(document).ready(function () {
updt_line();
} else if (activity == 6) {
showAndBlock([0, 4]);
- $("#userValidacaoCompras").val($("#currentUserName").val());
- $("#dataValidacaoCompras").val(
- requestDate[0] + " - " + requestDate[1]
- );
+ if ($("#usuarioEmissorNfe").val() == "") {
+ $("#usuarioEmissorNfe").val($("#currentUserName").val());
+ }
+ if ($("#dataEmissaoNfe").val() == "") {
+ $("#dataEmissaoNfe").val(
+ requestDate[0] + " - " + requestDate[1]
+ );
+ }
if ($("#justificativaDecisaoGestor").val() == "") {
$(".justificativa-activity-4").hide();
@@ -66,6 +98,9 @@ $(document).ready(function () {
$("#dataAprovCompras").val(
requestDate[0] + " - " + requestDate[1]
);
+ $("#blocoTipoMotoristaEntrega, #blocoOutroMotoristaEntrega").hide();
+ $("input[name='tipoMotoristaEntrega']").prop("disabled", true);
+ $("#motoristaEntregaSelecionado").prop("disabled", true);
showAndBlock([0, 4, 6]);
if ($("#justificativaDecisaoGestor").val() == "") {
@@ -81,7 +116,21 @@ $(document).ready(function () {
$("#dataRealizacaoCompras").val(
requestDate[0] + " - " + requestDate[1]
);
- showAndBlock([0, 4, 6, 57]);
+ if ($("#motoristaColetaNome").val() == "") {
+ $("#motoristaColetaNome").val($("#currentUserName").val());
+ }
+ if ($("#motoristaColetaLogin").val() == "") {
+ $("#motoristaColetaLogin").val($("#currentUserId").val());
+ }
+ if ($("#dataColeta").val() == "") {
+ $("#dataColeta").val(requestDate[0] + " " + requestDate[1]);
+ }
+ initMotoristaEntregaEscolha();
+ $("#blocoTipoMotoristaEntrega").show();
+ $("input[name='tipoMotoristaEntrega']").prop("disabled", false);
+ $("#motoristaEntregaSelecionado").prop("disabled", false);
+ // Mantem apenas etapas anteriores bloqueadas; card de coleta e entrega estao separados.
+ showAndBlock([0, 4, 6]);
if ($("#justificativaDecisaoGestor").val() == "") {
$(".justificativa-activity-4").hide();
@@ -111,9 +160,11 @@ $(document).ready(function () {
$("input[name=validacaoItens]").on("change", function () {
$(".justificativaDecisaoItens").hide();
+ var validacaoItensSelecionada = $("input[name=validacaoItens]:checked").val();
if (
- $("input[name=validacaoItens]:checked").val() == "incorreto" ||
- $("input[name=validacaoItens]:checked").val() == "naoEntregue"
+ validacaoItensSelecionada == "divergencia" ||
+ validacaoItensSelecionada == "incorreto" ||
+ validacaoItensSelecionada == "naoEntregue"
) {
$(".justificativaDecisaoItens").show();
}
@@ -146,6 +197,7 @@ $(document).ready(function () {
invisibleBtnUpload("fdAnexo_Coleta");
invisibleBtnUpload("fdAnexo_Entrega");
invisibleBtnUpload("fdAnexo_recebimento");
+ processarConferenciaNfe();
// gerarTabelaCotacaoIndica("tabelaCotacaoIndica", "tabelaItens");
@@ -238,6 +290,589 @@ function getCurrentDate() {
return currentDate;
}
+function initMotoristaEntregaEscolha() {
+ var escolha = String($("input[name='tipoMotoristaEntrega']:checked").val() || "");
+ if (!escolha) {
+ var coletaLogin = String($("#motoristaColetaLogin").val() || "").trim();
+ var entregaLogin = String($("#motoristaEntregaLogin").val() || "").trim();
+ if (entregaLogin && coletaLogin && entregaLogin !== coletaLogin) {
+ escolha = "outro";
+ } else {
+ escolha = $("#motoristaColetaNome").val() ? "mesmo" : "outro";
+ }
+ $("input[name='tipoMotoristaEntrega'][value='" + escolha + "']").prop("checked", true);
+ }
+ applyMotoristaEntregaMode(escolha, true);
+}
+
+function applyMotoristaEntregaMode(mode, keepValues) {
+ var escolha = String(mode || "");
+ var blocoOutro = $("#blocoOutroMotoristaEntrega");
+ if (!blocoOutro.length) return;
+
+ if (escolha === "outro") {
+ blocoOutro.show();
+ loadMotoristasEntregaSelect(false);
+ if (!keepValues) {
+ $("#motoristaEntregaNome").val("");
+ $("#motoristaEntregaLogin").val("");
+ clearZoomField("motoristaEntregaSelecionado");
+ } else {
+ syncMotoristaEntregaSelectFromHidden();
+ }
+ return;
+ }
+
+ blocoOutro.hide();
+ if (escolha === "mesmo") {
+ var coletaNome = String($("#motoristaColetaNome").val() || "").trim();
+ var coletaLogin = String($("#motoristaColetaLogin").val() || "").trim();
+ if (coletaNome) $("#motoristaEntregaNome").val(coletaNome);
+ if (coletaLogin) $("#motoristaEntregaLogin").val(coletaLogin);
+ }
+}
+
+function clearZoomField(fieldId) {
+ try {
+ if (window[fieldId] && typeof window[fieldId].clear === "function") {
+ window[fieldId].clear();
+ }
+ } catch (e) {}
+
+ try {
+ if (window[fieldId] && typeof window[fieldId].setValue === "function") {
+ window[fieldId].setValue("");
+ }
+ } catch (e2) {}
+
+ $("#" + fieldId).val("");
+}
+
+var MOTORISTAS_GROUP_ID = "Motoristas";
+var motoristasEntregaCache = null;
+var motoristasEntregaLoading = false;
+
+function loadMotoristasEntregaSelect(forceReload) {
+ var select = $("#motoristaEntregaSelecionado");
+ if (!select.length) return;
+
+ if (!forceReload && motoristasEntregaCache && motoristasEntregaCache.length) {
+ renderMotoristasEntregaOptions(motoristasEntregaCache);
+ return;
+ }
+
+ if (motoristasEntregaLoading) return;
+
+ motoristasEntregaLoading = true;
+
+ var requestPayload = {
+ name: "ds_motoristas_grupo",
+ fields: null,
+ constraints: [{
+ _field: "GROUP_ID",
+ _initialValue: MOTORISTAS_GROUP_ID,
+ _finalValue: MOTORISTAS_GROUP_ID,
+ _type: 1
+ }],
+ order: null
+ };
+
+ $.ajax({
+ type: "POST",
+ url: "/api/public/ecm/dataset/datasets/",
+ contentType: "application/json",
+ dataType: "json",
+ data: JSON.stringify(requestPayload)
+ }).done(function (response) {
+ var values = ((((response || {}).content || {}).values) || []);
+ motoristasEntregaCache = normalizeMotoristasEntregaRows(values);
+ renderMotoristasEntregaOptions(motoristasEntregaCache);
+ }).fail(function (xhr) {
+ console.error("Falha ao carregar motoristas do dataset:", xhr);
+ motoristasEntregaCache = [];
+ renderMotoristasEntregaOptions([]);
+ }).always(function () {
+ motoristasEntregaLoading = false;
+ });
+}
+
+function normalizeMotoristasEntregaRows(values) {
+ var out = [];
+ var map = {};
+
+ for (var i = 0; i < values.length; i++) {
+ var row = values[i] || {};
+ var colleagueId = String(row.COLLEAGUE_ID || row.colleagueId || row.colleagueid || "").trim();
+ if (!colleagueId) continue;
+ if (map[colleagueId]) continue;
+ map[colleagueId] = true;
+
+ out.push({
+ COLLEAGUE_ID: colleagueId,
+ NOME: String(row.NOME || row.colleagueName || row.nome || "").trim(),
+ LOGIN: String(row.LOGIN || row.login || "").trim(),
+ EMAIL: String(row.EMAIL || row.mail || row.email || "").trim()
+ });
+ }
+
+ out.sort(function (a, b) {
+ var aNome = (a.NOME || a.LOGIN || a.COLLEAGUE_ID).toLowerCase();
+ var bNome = (b.NOME || b.LOGIN || b.COLLEAGUE_ID).toLowerCase();
+ return aNome < bNome ? -1 : (aNome > bNome ? 1 : 0);
+ });
+
+ return out;
+}
+
+function renderMotoristasEntregaOptions(rows) {
+ var select = $("#motoristaEntregaSelecionado");
+ if (!select.length) return;
+
+ var selectedValue = String($("#motoristaEntregaLogin").val() || select.val() || "").trim();
+
+ select.empty();
+ select.append($("").val("").text("Selecione o motorista"));
+
+ for (var i = 0; i < rows.length; i++) {
+ var row = rows[i];
+ var nome = String(row.NOME || row.LOGIN || row.COLLEAGUE_ID);
+ var label = row.LOGIN ? (nome + " (" + row.LOGIN + ")") : nome;
+ var option = $("")
+ .val(row.COLLEAGUE_ID)
+ .text(label)
+ .attr("data-nome", nome)
+ .attr("data-login", String(row.LOGIN || ""));
+ select.append(option);
+ }
+
+ if (selectedValue) {
+ select.val(selectedValue);
+ }
+
+ if (!select.val()) {
+ // Limpa selecao visual quando o valor salvo nao existe mais no dataset.
+ select.val("");
+ }
+
+ applySelectedMotoristaEntregaOption();
+}
+
+function syncMotoristaEntregaSelectFromHidden() {
+ var select = $("#motoristaEntregaSelecionado");
+ if (!select.length) return;
+
+ var storedId = String($("#motoristaEntregaLogin").val() || "").trim();
+ if (!storedId) {
+ select.val("");
+ return;
+ }
+
+ select.val(storedId);
+ if (select.val()) {
+ applySelectedMotoristaEntregaOption();
+ }
+}
+
+function applySelectedMotoristaEntregaOption() {
+ var select = $("#motoristaEntregaSelecionado");
+ if (!select.length) return;
+
+ var selectedId = String(select.val() || "").trim();
+ if (!selectedId) {
+ if (String($("input[name='tipoMotoristaEntrega']:checked").val() || "") === "outro") {
+ $("#motoristaEntregaNome").val("");
+ $("#motoristaEntregaLogin").val("");
+ }
+ return;
+ }
+
+ var option = select.find("option:selected");
+ var nome = String(option.attr("data-nome") || option.text() || "").trim();
+
+ $("#motoristaEntregaLogin").val(selectedId);
+ $("#motoristaEntregaNome").val(nome);
+ $("#tipoMotoristaEntregaOutro").prop("checked", true);
+}
+
+function normalizeNfeKey(value) {
+ return String(value == null ? "" : value).replace(/\D/g, "").substring(0, 44);
+}
+
+function clearNfeConsultaFields() {
+ $("#numeroNfeConsulta").val("");
+ $("#serieNfeConsulta").val("");
+ $("#dataEmissaoApiNfe").val("");
+ $("#situacaoNfeConsulta").val("");
+ $("#fornecedorNfeConsulta").val("");
+ $("#valorNfeConsulta").val("");
+ $("#dataEntradaNfeConsulta").val("");
+ $("#itensNfeConsulta").val("");
+ $("#operacaoNfeConsulta").val("");
+ $("#lojaNfeConsulta").val("");
+ $("#invoiceIdNfeConsulta").val("");
+ $("#storeIdNfeConsulta").val("");
+ $("#itensNfeJson").val("[]");
+ $("#qtdDivergenciasNfe").val("0");
+ renderTabelaConferencia([], 0, 0, "Consulte a chave da NFe para gerar o confronto dos itens.", "info");
+}
+
+function setNfeFeedback(message, type) {
+ var feedback = $("#consultaNfeFeedback");
+ if (!feedback.length) {
+ return;
+ }
+
+ feedback.removeClass("alert-success alert-danger alert-info alert-warning");
+
+ if (!message || type === "hidden") {
+ feedback.hide().text("");
+ return;
+ }
+
+ if (type === "success") {
+ feedback.addClass("alert-success");
+ } else if (type === "warning") {
+ feedback.addClass("alert-warning");
+ } else if (type === "info") {
+ feedback.addClass("alert-info");
+ } else {
+ feedback.addClass("alert-danger");
+ }
+
+ feedback.text(message).show();
+}
+
+function formatNfeCurrency(value) {
+ var textValue = String(value == null ? "" : value).trim();
+ if (textValue === "") {
+ return "";
+ }
+
+ var numberValue = parseFloat(textValue.replace(",", "."));
+ if (isNaN(numberValue)) {
+ return textValue;
+ }
+
+ try {
+ return numberValue.toLocaleString("pt-BR", { style: "currency", currency: "BRL" });
+ } catch (e) {
+ return textValue;
+ }
+}
+
+function fillNfeConsultaFields(row) {
+ var emissionDate = String(row.emissionDate || "");
+
+ $("#numeroNfeConsulta").val(String(row.invoiceNumber || ""));
+ $("#serieNfeConsulta").val(String(row.serie || ""));
+ $("#dataEmissaoApiNfe").val(emissionDate);
+ $("#situacaoNfeConsulta").val(String(row.situation || ""));
+ $("#fornecedorNfeConsulta").val(String(row.supplierName || ""));
+ $("#valorNfeConsulta").val(formatNfeCurrency(row.documentValue));
+ $("#dataEntradaNfeConsulta").val(String(row.updatedAt || ""));
+ $("#itensNfeConsulta").val(String(row.itemCount || ""));
+ $("#operacaoNfeConsulta").val(String(row.fiscalOperationDescription || ""));
+ $("#lojaNfeConsulta").val(String(row.storeId || ""));
+ $("#invoiceIdNfeConsulta").val(String(row.invoiceId || ""));
+ $("#storeIdNfeConsulta").val(String(row.storeId || ""));
+ $("#itensNfeJson").val(String(row.itensJson || "[]"));
+
+ if (emissionDate) {
+ $("#dataEmissaoNfe").val(emissionDate);
+ }
+
+ processarConferenciaNfe();
+}
+
+function processarConferenciaNfe() {
+ var nfeItems = parseItensNfeJson();
+ if (nfeItems.length === 0) {
+ $("#qtdDivergenciasNfe").val("0");
+ renderTabelaConferencia([], 0, 0, "Consulte a chave da NFe para gerar o confronto dos itens.", "info");
+ return;
+ }
+
+ var solicitacaoMap = buildSolicitacaoMap();
+ var nfeMap = buildNfeMap(nfeItems);
+ var allKeys = mergeKeys(solicitacaoMap, nfeMap);
+ var rows = [];
+ var divergencias = 0;
+
+ for (var i = 0; i < allKeys.length; i++) {
+ var key = allKeys[i];
+ var req = solicitacaoMap[key] || { qty: 0, label: key };
+ var nfe = nfeMap[key] || { qty: 0, label: key };
+
+ var status = "OK";
+ if (req.qty === 0 && nfe.qty > 0) {
+ status = "Somente NFe";
+ } else if (nfe.qty === 0 && req.qty > 0) {
+ status = "Somente solicitacao";
+ } else if (Math.abs(req.qty - nfe.qty) > 0.00001) {
+ status = "Quantidade divergente";
+ }
+
+ if (status !== "OK") {
+ divergencias++;
+ }
+
+ rows.push({
+ key: req.label || nfe.label || key,
+ requestedQty: req.qty,
+ nfeQty: nfe.qty,
+ status: status
+ });
+ }
+
+ $("#qtdDivergenciasNfe").val(String(divergencias));
+
+ var resumo = "Conferencia finalizada: " + rows.length + " item(ns), " + divergencias + " divergencia(s).";
+ var resumoType = divergencias > 0 ? "warning" : "success";
+ renderTabelaConferencia(rows, rows.length, divergencias, resumo, resumoType);
+}
+
+function parseItensNfeJson() {
+ var raw = String($("#itensNfeJson").val() || "[]");
+ try {
+ var parsed = JSON.parse(raw);
+ return parsed instanceof Array ? parsed : [];
+ } catch (e) {
+ return [];
+ }
+}
+
+function buildSolicitacaoMap() {
+ var out = {};
+ $("input[name^='quantidadeItem___']").each(function () {
+ var name = $(this).attr("name") || "";
+ var indice = name.split("___")[1];
+ if (!indice) return;
+
+ var qty = toFloatSafe($(this).val());
+ if (qty <= 0) return;
+
+ var productId = String($("#productIdItem___" + indice).val() || "").trim();
+ var code = resolveSolicitacaoItemCode(indice, $(this));
+ var descricao = String($("#codigoItem___" + indice).val() || "").trim();
+
+ var key = resolveConferenciaKey(productId, code, "ROW:" + indice);
+ var label = productId ? ("PID " + productId) : (code || descricao || ("Linha " + indice));
+
+ if (!out[key]) {
+ out[key] = { qty: 0, label: label };
+ }
+ out[key].qty += qty;
+ });
+ return out;
+}
+
+function resolveSolicitacaoItemCode(indice, qtyInput) {
+ var code = String($("#codigoProdutoItem___" + indice).val() || "").trim();
+ if (code) return normalizeCodigoComparacao(code);
+
+ code = String($("#descricao___" + indice).val() || "").trim();
+ if (code) return normalizeCodigoComparacao(code);
+
+ var row = qtyInput && qtyInput.length ? qtyInput.closest("tr") : $();
+ if (row.length) {
+ var byName = findFirstFilledValue(row.find("input[name='descricao___" + indice + "']"));
+ if (byName) return normalizeCodigoComparacao(byName);
+
+ var anyDescricao = findFirstFilledValue(row.find("input[name^='descricao']"));
+ if (anyDescricao) return normalizeCodigoComparacao(anyDescricao);
+
+ var byIdLike = findFirstFilledValue(row.find("input[id*='descricao']"));
+ if (byIdLike) return normalizeCodigoComparacao(byIdLike);
+
+ var codigoCellInputs = row.find("td").eq(1).find("input,select,textarea");
+ var fromCodigoCell = findFirstFilledValue(codigoCellInputs);
+ if (fromCodigoCell) return normalizeCodigoComparacao(fromCodigoCell);
+
+ // Em modo bloqueado/view, o Zoom pode renderizar apenas texto em span/div.
+ var codigoCell = row.find("td").eq(1);
+ var zoomRendered = findFirstFilledText(codigoCell.find(
+ ".select2-selection__rendered, .select2-chosen, .zoom-value, .zoom-span, span, div"
+ ));
+ if (zoomRendered) return normalizeCodigoComparacao(zoomRendered);
+
+ // Fallback final: texto bruto da célula.
+ var rawCellText = String(codigoCell.text() || "").trim();
+ if (rawCellText) return normalizeCodigoComparacao(rawCellText);
+ }
+
+ return "";
+}
+
+function findFirstFilledValue(elements) {
+ if (!elements || !elements.length) return "";
+
+ for (var i = 0; i < elements.length; i++) {
+ var $el = $(elements[i]);
+ var val = String($el.val() || "").trim();
+ if (!val) {
+ val = String($el.attr("value") || "").trim();
+ }
+ if (!val) {
+ val = String($el.attr("data-value") || "").trim();
+ }
+ if (val) return val;
+ }
+ return "";
+}
+
+function findFirstFilledText(elements) {
+ if (!elements || !elements.length) return "";
+
+ for (var i = 0; i < elements.length; i++) {
+ var txt = String($(elements[i]).text() || "").trim();
+ if (txt) return txt;
+ }
+ return "";
+}
+
+function normalizeCodigoComparacao(value) {
+ var raw = String(value || "").trim();
+ if (!raw) return "";
+
+ // Zoom pode trazer "75655 - DESCRICAO"; para conferencia usamos o primeiro token.
+ var firstToken = raw.split(" - ")[0].split(" | ")[0].trim();
+ return firstToken || raw;
+}
+
+function buildNfeMap(items) {
+ var out = {};
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i] || {};
+ var qty = toFloatSafe(item.quantity);
+ if (qty <= 0) continue;
+
+ var productId = String(item.productId || "").trim();
+ var code = String(item.code || "").trim();
+ var key = resolveConferenciaKey(productId, code, "NFE:" + i);
+ var label = productId ? ("PID " + productId) : (code || ("Item NFe " + (i + 1)));
+
+ if (!out[key]) {
+ out[key] = { qty: 0, label: label };
+ }
+ out[key].qty += qty;
+ }
+ return out;
+}
+
+function resolveConferenciaKey(productId, code, fallback) {
+ var pid = String(productId || "").trim();
+ if (pid) {
+ return "ITEM:" + pid;
+ }
+
+ var cod = String(code || "").trim();
+ if (cod) {
+ return "ITEM:" + cod;
+ }
+
+ return String(fallback || "");
+}
+
+function mergeKeys(a, b) {
+ var obj = {};
+ for (var ka in a) obj[ka] = true;
+ for (var kb in b) obj[kb] = true;
+ return Object.keys(obj);
+}
+
+function renderTabelaConferencia(rows, totalItens, divergencias, mensagem, tipo) {
+ var tbody = $("#tabelaConferenciaNfeBody");
+ var resumo = $("#resumoConferenciaNfe");
+ if (!tbody.length || !resumo.length) return;
+
+ var html = "";
+ if (!rows || rows.length === 0) {
+ html = "