Validador

// Código: verificar_acesso.gs const SPREADSHEET_ID = "1sAMUEDOqmzR3yAPpriWMp1xj-zAP7jTHsTlgWlVUaTY"; const SHEET_NAME = "COMPRA COMPLETA"; // nome da aba function doGet(e) { // Parâmetros esperados: permissao (email), produto const email = (e.parameter.permissao || "").trim(); const produto = (e.parameter.produto || "").trim(); // cabeçalhos anti-cache const headers = { "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0" }; if (!email || !produto) { return ContentService .createTextOutput(JSON.stringify({ error: "Parâmetros 'permissao' (email) e 'produto' são obrigatórios." })) .setMimeType(ContentService.MimeType.JSON) .setHeaders(headers); } try { const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME); if (!sheet) { throw new Error("Aba '" + SHEET_NAME + "' não encontrada."); } const data = sheet.getDataRange().getValues(); if (data.length < 2) { return jsonResponse({ error: "Planilha sem dados." }, headers); } const header = data[0].map(h => (h || "").toString().trim()); // localizar colunas por nome const colIndex = {}; ["Produto","SKU/ID","Email","Nome","Sobrenome","Telefone","Endereço","Cidade","Estado","CEP","País","Valor","Moeda","Parcelas","Status","Data","Transação"].forEach(name=>{ const idx = header.indexOf(name); if (idx >= 0) colIndex[name] = idx; }); if (!colIndex["Email"] || !colIndex["Produto"] || !colIndex["Data"] || !colIndex["Status"] || !colIndex["Transação"]) { // se algum não foi encontrado, tenta relaxado // use índices já mesmos se már suceder } // coleta linhas que batem com email+produto const matchedRows = []; for (let i = 1; i < data.length; i++) { const row = data[i]; const rowProduto = (row[colIndex["Produto"]] || "").toString().trim(); const rowEmail = (row[colIndex["Email"]] || "").toString().trim(); const rowDataStr = (row[colIndex["Data"]] || "").toString().trim(); const rowStatus = (row[colIndex["Status"]] || "").toString().trim(); const rowTransacao = (row[colIndex["Transação"]] || "").toString().trim(); if (rowEmail.toLowerCase() === email.toLowerCase() && rowProduto === produto) { const parsedDate = parseBrazilDateTime(rowDataStr); matchedRows.push({ produto: rowProduto, sku: (row[colIndex["SKU/ID"]]||"").toString(), email: rowEmail, status: rowStatus, dataStr: rowDataStr, dateObj: parsedDate, transacao: rowTransacao }); } } if (matchedRows.length === 0) { return jsonResponse({ pode_usar: false, mensagem: "Nenhuma compra encontrada para esse e-mail e produto." }, headers); } // Agrupar por transacao e pegar o último status (data maior) por transação const groups = {}; matchedRows.forEach(r=>{ const t = r.transacao || ("__no_tx__:" + r.dataStr); if (!groups[t]) groups[t] = []; groups[t].push(r); }); const transacoesResumo = []; for (const tx in groups) { const items = groups[tx]; items.sort((a,b)=> b.dateObj - a.dateObj); // mais recente primeiro const last = items[0]; transacoesResumo.push({ transacao: tx, ultimo_status: last.status, ultimo_data: last.dataStr, ultimo_data_obj: last.dateObj.getTime() }); } // escolher a transacao com ultimo_data_obj mais recente transacoesResumo.sort((a,b)=> b.ultimo_data_obj - a.ultimo_data_obj); const maisRecente = transacoesResumo[0]; // Mensagens por status const status = (maisRecente.ultimo_status || "").toUpperCase(); const mensagensPorStatus = { "COMPLETED": "Acesso liberado. Transação finalizada.", "APPROVED": "Pagamento aprovado, mas verifique se foi finalizado (status final não é COMPLETED).", "BILLET_PRINTED": "Boleto impresso — aguardando pagamento.", "CANCELED": "Compra cancelada — acesso negado.", "DELAYED": "Pagamento atrasado/diferido — acesso negado.", "DISPUTE": "Compra em disputa — acesso negado.", "EXPIRED": "Compra expirada — acesso negado." }; const podeUsar = (status === "COMPLETED"); const mensagem = mensagensPorStatus[status] || ("Status: " + status); const resp = { pode_usar: podeUsar, transacao: maisRecente.transacao, status_final: status, mensagem: mensagem, detalhes: transacoesResumo.map(t=>({ transacao: t.transacao, ultimo_status: t.ultimo_status, ultimo_data: t.ultimo_data })) }; return jsonResponse(resp, headers); } catch (err) { return jsonResponse({ error: err.message }, headers); } } function jsonResponse(obj, headers) { const out = ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON); if (headers) { // Apps Script ContentService não permite setHeaders diretamente no returned object, // mas podemos setar Cache-Control via HtmlService? Como alternativa, incluímos header via meta no cliente e confiamos no fetch no lado cliente (no-cache). // Ainda assim retornamos o JSON normalmente. } return out; } function parseBrazilDateTime(s) { // espera "dd/mm/yyyy HH:MM:SS" ou "dd/mm/yyyy" if (!s) return new Date(0); s = s.trim(); const parts = s.split(' '); const datePart = parts[0]; const timePart = parts[1] || "00:00:00"; const d = datePart.split('/'); if (d.length !== 3) return new Date(s); // fallback const dd = pad(d[0],2); const mm = pad(d[1],2); const yyyy = d[2]; // construir string ISO evitando timezone issues const iso = `${yyyy}-${mm}-${dd}T${timePart}`; const dt = new Date(iso); // se inválido, tentar trocar ":" por ":" já ok — fallback final: if (isNaN(dt.getTime())) return new Date(0); return dt; } function pad(s, n) { s = s.toString(); while (s.length < n) s = '0' + s; return s; }

Formulário de contato

Nome

E-mail *

Mensagem *

Este blog é um complemento do nosso canal no YouTube. Clique em @CanalQb para seguir e acompanhar nossos vídeos!
Imagem

Microsoft Access VBA: Criando um validador de dígito eficaz e prático

@CanalQb

Microsoft Access VBA: Criando um validador de dígito eficaz e prático



Compartilho um exemplo prático e simples de como criar um validador de dígito utilizando VBA no Microsoft Access. Este código foi desenvolvido para gerar um dígito verificador para uma sequência de números, garantindo maior segurança e integridade dos dados.

O código a seguir valida o campo antes de realizar o cálculo e, caso o campo esteja vazio, solicita que o usuário preencha. Em seguida, ele calcula o dígito verificador com base na soma ponderada dos números em posições pares e ímpares.


If IsNull(t1.Value) Or t1.Value = "" Then
    MsgBox "Por favor, preencha o campo T1 antes de prosseguir."
    t1.SetFocus
Else
    Dim junta As String
    Dim conta As Integer
    Dim somaa As Integer
    Dim somab As Integer
    Dim total As Integer
    Dim digito As String
    Dim MOSTRA1 As String
    Dim MOSTRA2 As String

    junta = t1.Value

    ' Soma dos dígitos ímpares
    For conta = 1 To Len(junta) Step 2
        MOSTRA1 = Mid(junta, conta, 1)
        somaa = somaa + Val(MOSTRA1)
    Next conta

    soma1 = somaa * 3

    ' Soma dos dígitos pares
    For conta = 2 To Len(junta) Step 2
        MOSTRA2 = Mid(junta, conta, 1)
        somab = somab + Val(MOSTRA2)
    Next conta

    total = somab + soma1
    digito = Format((((total \ 10) + 1) * 10) - total, "00")

    t2.Value = digito
    t3.Value = junta & "-" & digito
End If
  

Explicando o código: a variável junta armazena a sequência numérica para a qual será gerado o dígito verificador. O algoritmo percorre a string, somando os dígitos em posições ímpares e pares, multiplicando a soma dos ímpares por 3, e depois calcula o dígito verificador baseado no módulo 10.

Este exemplo pode ser facilmente adaptado para validações personalizadas, de acordo com a regra de negócios do seu projeto, proporcionando maior confiabilidade ao tratamento de dados numéricos no Access.

Recomendamos também analisar as necessidades específicas do seu sistema para adaptar e melhorar o código conforme a complexidade do validador desejado.

Importante: Sempre crie frases de segurança únicas e utilize wallets seguras para armazenar dados sensíveis, especialmente em contextos de jogos, tokens ou criptomoedas. Analise cuidadosamente qualquer ferramenta antes de investir ou utilizá-la.

@CanalQb

Comentários