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 authVariants = buildAuthVariants(auth); var diagnostics = []; var query = "page=1&page_size=50&key=" + key + "&sort_by=updatedAt&sort_order=desc"; var endpoints = [ "/v2/vendas/rgb-transferencias?" + query, "v2/vendas/rgb-transferencias?" + query, "/rgb-transferencias?" + query ]; var apiObj = null; var hitInfo = ""; var lastApiMessage = ""; try { var clientService = fluigAPI.getAuthorizeClientService(); for (var i = 0; i < endpoints.length; i++) { var endpoint = endpoints[i]; for (var a = 0; a < authVariants.length; a++) { var authVariant = authVariants[a]; var resp = invokeAuthorizedGet(clientService, endpoint, authVariant); diagnostics.push(endpoint + " [" + authVariant.name + "] => 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 + " [" + authVariant.name + "]"; break; } } if (apiObj) { break; } } } catch (eService) { diagnostics.push("authorizeClientService exception: " + eService); } if (!apiObj) { var directUrls = [ "https://api.grupoginseng.com.br/v2/vendas/rgb-transferencias?" + query ]; for (var d = 0; d < directUrls.length; d++) { var url = directUrls[d]; for (var da = 0; da < authVariants.length; da++) { var directAuthVariant = authVariants[da]; var directResp = fetchDirect(url, 30000, directAuthVariant); diagnostics.push(url + " [" + directAuthVariant.name + "] => 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 + " [" + directAuthVariant.name + "]"; break; } } if (apiObj) { 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; } var dataNfe = extractInvoiceData(apiObj, key); if (!dataNfe) { addErrorRow(dataset, trim(apiObj.message) || "NFe nao encontrada. Fonte: " + hitInfo); return dataset; } var itens = resolveItems(dataNfe); var itensJson = JSON.stringify(buildNfeItems(itens)); dataset.addRow([ "true", "OK (" + hitInfo + ")", trim(dataNfe.key || dataNfe.nfeKey || dataNfe.chave || key), trim(dataNfe.invoiceNumber || dataNfe.numeroNota || dataNfe.numero || dataNfe.number), trim(dataNfe.serie || dataNfe.series), formatIsoDate(dataNfe.emissionDate || dataNfe.issueDate || dataNfe.invoiceDate), formatIsoDate(dataNfe.operationDate || dataNfe.transactionDate || dataNfe.operation_at), trim(dataNfe.supplierName || dataNfe.supplier || dataNfe.fornecedor || dataNfe.emitente), trim(dataNfe.documentValue || dataNfe.totalValue || dataNfe.valorDocumento || dataNfe.amount), trim(dataNfe.totalItemsValue || dataNfe.itemsValue || dataNfe.valorItens || dataNfe.totalValue), trim(dataNfe.situation || dataNfe.status), trim(dataNfe.fiscalOperationDescription || dataNfe.operationDescription || dataNfe.naturezaOperacao), String(itens.length), itensJson, trim(dataNfe.storeId || dataNfe.pdv || dataNfe.storeCode || dataNfe.lojaId), trim(dataNfe.invoiceId || dataNfe.id_venda || dataNfe.id || dataNfe.transferId), trim(dataNfe.emitterEmployeeId || dataNfe.emitterId || dataNfe.usuarioEmissor), formatIsoDateTime(dataNfe.updatedAt || dataNfe.modifiedAt || dataNfe.lastUpdate) ]); } 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 ""; var target = String(fieldName).toLowerCase(); for (var i = 0; i < constraints.length; i++) { var c = constraints[i]; if (!c || !c.fieldName) continue; if (String(c.fieldName).toLowerCase() === target) { return c.initialValue; } } return ""; } function resolveAuth(constraints) { var token = trim(getFirstConstraintValue(constraints, [ "token", "accessToken", "xAccessToken", "bearerToken", "access_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(getFirstConstraintValue(constraints, [ "basicUser", "username", "user" ])); var basicPass = trim(getFirstConstraintValue(constraints, [ "basicPass", "password", "pass" ])); // 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 getFirstConstraintValue(constraints, names) { if (!names || !(names instanceof Array)) return ""; for (var i = 0; i < names.length; i++) { var val = getConstraintValue(constraints, names[i]); if (trim(val)) return val; } return ""; } function buildAuthVariants(auth) { auth = auth || {}; var variants = []; var token = trim(auth.token); var basicUser = trim(auth.basicUser); var basicPass = trim(auth.basicPass); var basicHeader = buildBasicAuthHeader(basicUser, basicPass); if (token) { variants.push({ name: "Bearer+XToken", authorization: "Bearer " + token, xAccessToken: token }); variants.push({ name: "XToken", xAccessToken: token }); variants.push({ name: "Bearer", authorization: "Bearer " + token }); } if (basicHeader) { variants.push({ name: "Basic", authorization: basicHeader }); if (token) { variants.push({ name: "Basic+XToken", authorization: basicHeader, xAccessToken: token }); } } variants.push({ name: "NoAuth" }); return dedupeAuthVariants(variants); } function dedupeAuthVariants(variants) { var out = []; var seen = {}; for (var i = 0; i < variants.length; i++) { var v = variants[i] || {}; var signature = trim(v.authorization) + "|" + trim(v.xAccessToken); if (seen[signature]) continue; seen[signature] = true; out.push(v); } if (!out.length) { out.push({ name: "NoAuth" }); } return out; } function invokeAuthorizedGet(clientService, endpoint, authVariant) { var headers = { "Accept": "application/json" }; applyAuthHeaders(headers, authVariant); var data = { companyId: String(getValue("WKCompany") || "1"), serviceCode: "Fastapi", 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) return false; if (obj.success === true) return true; if (String(obj.success).toLowerCase() === "true") return true; if (obj.data || obj.items || obj.result || obj.content) return true; return false; } function extractInvoiceData(apiObj, expectedKey) { if (!apiObj) return null; var normalizedKey = normalizeDigits(expectedKey); return extractInvoiceFromNode(apiObj, normalizedKey); } function extractInvoiceFromNode(node, normalizedKey) { if (!node) return null; if (typeof node === "string") { var parsed = parseJsonSafe(node); if (!parsed) return null; return extractInvoiceFromNode(parsed, normalizedKey); } if (node instanceof Array) { return extractInvoiceFromArray(node, normalizedKey); } if (matchesInvoiceObject(node, normalizedKey)) { return node; } var nestedCandidates = [ node.data, node.items, node.rows, node.results, node.content, node.result, node.list, node.transferencias, node.rgbTransferencias ]; for (var i = 0; i < nestedCandidates.length; i++) { var nested = extractInvoiceFromNode(nestedCandidates[i], normalizedKey); if (nested) return nested; } return null; } function extractInvoiceFromArray(list, normalizedKey) { if (!list || !(list instanceof Array) || list.length === 0) return null; for (var i = 0; i < list.length; i++) { var item = list[i]; if (matchesInvoiceObject(item, normalizedKey)) { return item; } } return list[0] || null; } function matchesInvoiceObject(item, normalizedKey) { if (!item || item instanceof Array || typeof item !== "object") return false; var keyCandidate = normalizeDigits(item.key || item.nfeKey || item.chave || item.invoiceKey || item.nfe_key); if (normalizedKey && keyCandidate) { return keyCandidate === normalizedKey; } if (keyCandidate) return true; var hasIdentity = trim(item.invoiceNumber || item.numeroNota || item.invoiceId || item.transferId); return !!hasIdentity; } function resolveItems(dataNfe) { if (!dataNfe || typeof dataNfe !== "object") return []; var candidates = [ dataNfe.itens, dataNfe.itensJson, dataNfe.items, dataNfe.products, dataNfe.produtos ]; for (var i = 0; i < candidates.length; i++) { var raw = candidates[i]; if (!raw) continue; if (raw instanceof Array) { return raw; } if (typeof raw === "string") { var parsed = parseJsonSafe(raw); if (parsed instanceof Array) { return parsed; } } } return []; } 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 authHeaders = {}; applyAuthHeaders(authHeaders, auth); for (var h in authHeaders) { if (!authHeaders.hasOwnProperty(h)) continue; if (!authHeaders[h]) continue; conn.setRequestProperty(h, String(authHeaders[h])); } 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 applyAuthHeaders(headers, authVariant) { headers = headers || {}; authVariant = authVariant || {}; var authorization = trim(authVariant.authorization); var xAccessToken = trim(authVariant.xAccessToken); if (authorization) { headers.Authorization = authorization; } if (xAccessToken) { headers["x-access-token"] = xAccessToken; } } function buildBasicAuthHeader(basicUser, basicPass) { var user = trim(basicUser); var pass = trim(basicPass); if (!user || !pass) return ""; var raw = String(user) + ":" + String(pass); var bytes = new java.lang.String(raw).getBytes("UTF-8"); var encoded = java.util.Base64.getEncoder().encodeToString(bytes); return "Basic " + String(encoded); } 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 || item.productId), unitValue: toNumber(item.unitValue || item.unit_value || item.value) }); } 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; } }