E aí, Jovens com Propósito! 👋
Acompanhe tudo o que está rolando no nosso ministério.
Instalar Aplicativo Grátis
Carregando...
Procurando próximas programações...
00
d
00
h
00
m
00
s
--
00
---
--:--
Links Rápidos
- Carregando...
Agenda Geral 📅
Confira os dias e locais de todas as programações.
Mural de Avisos 📢
Fique por dentro das novidades e devocionais diários.
Devocional do Dia
"Lembre-se do seu Criador nos dias da sua mocidade..."
Eclesiastes 12:1
Aproveite a sua juventude para buscar ao Senhor com todo o seu coração. O vigor e a energia que você tem hoje são dons preciosos para abençoar vidas e edificar o Reino de Deus!
Avisos Recentes
Escalas do Próximo Culto 📋
Acesso de Líderes
Faça login com seu usuário e senha.
Painel de Líderes ⚡
Cadastrar Novo Evento
Gerenciar Eventos Cadastrados
Gerenciar Categorias
Atualizar Devocional Diário
Criar Novo Aviso
Gerenciar Avisos
Playlist do YouTube Music
🎙️ Podcast Jovens com Propósito (YouTube)
Episódios do Podcast Cadastrados
📸 Configurações de Redes Sociais
👥 Gerenciar Equipe (Líderes e Apoio)
Adicionar Novo
Equipe Atual
Cadastrar Nova Escala
Gerenciar Escalas Cadastradas
Resumo Financeiro 💰
R$ 0,00
Receitas
R$ 0,00
Despesas
R$ 0,00
Saldo Disponível
Novo Lançamento Financeiro 📝
Histórico de Lançamentos
Sincronização em Nuvem (Google Drive) 💾
Sincronize em tempo real todas as alterações (agenda, avisos, escalas, membros e finanças) salvando um arquivo JSON diretamente no seu **Google Drive**.
Como configurar no seu Google Drive (Passo a Passo) ℹ️
- Acesse o Google Apps Script com sua conta Google.
- Clique em Novo projeto.
- Apague todo o código existente e cole o código abaixo:
const FILE_NAME = "gj_connect_data.json";
const SPREADSHEET_ID = "1Tm09fo6EpkdrFlsM8GWMHkr2TiwKlodj72NL557uqM4";
const FORM_SPREADSHEET_ID = "1RNu6Iege7MMo6D5-R-oAbzwZqpWBD_5lx4Gdzqv-jmI";
function getFinanceSheet(ss) {
var gid = 1878233712;
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetId() == gid) {
return sheets[i];
}
}
var sheet = ss.getSheetByName("App Finança") || ss.getSheetByName("App Financa") || ss.getSheetByName("Finanças") || ss.getSheetByName("Financas");
if (!sheet && sheets.length > 0) {
sheet = sheets[0];
}
return sheet;
}
function getGoogleSheetFinance() {
var financeList = [];
try {
var ss = SpreadsheetApp.openById(SPREADSHEET_ID);
var sheet = getFinanceSheet(ss);
if (sheet) {
var data = sheet.getDataRange().getValues();
if (data.length > 1) {
var headerRowIdx = 0;
for (var r = 0; r < Math.min(10, data.length); r++) {
var rowCells = data[r].map(function(c) { return String(c).trim().toLowerCase(); });
if (rowCells.indexOf("data") !== -1 || rowCells.indexOf("descrição") !== -1 || rowCells.indexOf("descricao") !== -1 || rowCells.indexOf("receita") !== -1 || rowCells.indexOf("despesa") !== -1) {
headerRowIdx = r;
break;
}
}
var headers = data[headerRowIdx].map(function(h) { return String(h).trim().toLowerCase(); });
// Find column indices
var dateIdx = headers.indexOf("data") !== -1 ? headers.indexOf("data") : 0;
var descIdx = headers.indexOf("descrição") !== -1 ? headers.indexOf("descrição") :
headers.indexOf("descricao") !== -1 ? headers.indexOf("descricao") :
headers.indexOf("nome") !== -1 ? headers.indexOf("nome") :
headers.indexOf("histórico") !== -1 ? headers.indexOf("histórico") :
headers.indexOf("historico") !== -1 ? headers.indexOf("historico") : 1;
var tipoIdx = headers.indexOf("tipo") !== -1 ? headers.indexOf("tipo") : -1;
var entradaIdx = headers.indexOf("entrada") !== -1 ? headers.indexOf("entrada") :
headers.indexOf("entradas") !== -1 ? headers.indexOf("entradas") :
headers.indexOf("receita") !== -1 ? headers.indexOf("receita") :
headers.indexOf("receitas") !== -1 ? headers.indexOf("receitas") : 3;
var saidaIdx = headers.indexOf("saída") !== -1 ? headers.indexOf("saída") :
headers.indexOf("saida") !== -1 ? headers.indexOf("saida") :
headers.indexOf("saídas") !== -1 ? headers.indexOf("saídas") :
headers.indexOf("despesa") !== -1 ? headers.indexOf("despesa") :
headers.indexOf("despesas") !== -1 ? headers.indexOf("despesas") :
headers.indexOf("dispesa") !== -1 ? headers.indexOf("dispesa") :
headers.indexOf("dispesas") !== -1 ? headers.indexOf("dispesas") : 4;
var valorIdx = headers.indexOf("valor");
for (var r = headerRowIdx + 1; r < data.length; r++) {
var row = data[r];
var rawDate = dateIdx < row.length ? row[dateIdx] : "";
var dateStr = "";
if (rawDate instanceof Date) {
dateStr = rawDate.toISOString().split('T')[0];
} else if (rawDate) {
dateStr = String(rawDate).trim();
if (dateStr.indexOf("/") !== -1) {
var parts = dateStr.split("/");
if (parts.length === 3) {
dateStr = parts[2] + "-" + parts[1].padStart(2,"0") + "-" + parts[0].padStart(2,"0");
}
}
}
if (!dateStr) {
dateStr = new Date().toISOString().split('T')[0];
}
var desc = descIdx < row.length ? String(row[descIdx]).trim() : "";
if (!desc) continue;
// Ignore summary/total rows at the bottom of the sheet
var descLower = desc.toLowerCase();
if (descLower.indexOf("total") !== -1 || descLower.indexOf("saldo") !== -1 || descLower.indexOf("caixa") !== -1 || descLower.indexOf("subtotal") !== -1) {
continue;
}
var tipo = tipoIdx !== -1 && tipoIdx < row.length ? String(row[tipoIdx]).trim() : "";
if (entradaIdx !== -1 || saidaIdx !== -1) {
var entVal = 0;
var saiVal = 0;
if (entradaIdx !== -1 && entradaIdx < row.length) {
entVal = parseFloat(row[entradaIdx]) || 0;
}
if (saidaIdx !== -1 && saidaIdx < row.length) {
saiVal = parseFloat(row[saidaIdx]) || 0;
}
if (entVal > 0) {
financeList.push({
id: "sheet-ent-" + r,
name: "[Planilha] " + desc,
type: tipo || "Oferta",
value: entVal,
date: dateStr,
updatedAt: new Date(2000, 0, 1).toISOString()
});
}
if (saiVal > 0) {
financeList.push({
id: "sheet-sai-" + r,
name: "[Planilha] " + desc,
type: tipo || "Saída",
value: saiVal,
date: dateStr,
updatedAt: new Date(2000, 0, 1).toISOString()
});
}
} else if (valorIdx !== -1 && valorIdx < row.length) {
var val = parseFloat(row[valorIdx]) || 0;
var isSaida = (tipo.toLowerCase().indexOf("saida") !== -1 || tipo.toLowerCase().indexOf("saída") !== -1 || tipo.toLowerCase().indexOf("despesa") !== -1 || tipo.toLowerCase().indexOf("dispesa") !== -1 || val < 0);
if (val !== 0) {
financeList.push({
id: "sheet-row-" + r,
name: "[Planilha] " + desc,
type: isSaida ? "Saída" : (tipo || "Oferta"),
value: Math.abs(val),
date: dateStr,
updatedAt: new Date(2000, 0, 1).toISOString()
});
}
}
}
}
}
} catch (err) {
Logger.log("Erro ao ler planilha: " + err.toString());
financeList.push({
id: "sheet-error-log",
name: "[ERRO PLANILHA]: " + err.toString() + " (Planilha ID: " + SPREADSHEET_ID + ")",
type: "Despesa",
value: 0,
date: new Date().toISOString().split('T')[0],
updatedAt: new Date(2000, 0, 1).toISOString()
});
}
return financeList;
}
function getGoogleSheetCampRegistrations() {
var registrations = [];
try {
var ss = SpreadsheetApp.openById(FORM_SPREADSHEET_ID);
var sheet = ss.getSheets()[0];
var data = sheet.getDataRange().getValues();
if (data.length > 1) {
for (var r = 1; r < data.length; r++) {
var row = data[r];
var timestamp = row[0];
var name = row[1] ? String(row[1]).trim() : "";
if (!name) continue;
var dateStr = "";
if (timestamp instanceof Date) {
dateStr = timestamp.toISOString().split('T')[0];
} else if (timestamp) {
dateStr = String(timestamp).split(' ')[0];
}
if (!dateStr) dateStr = new Date().toISOString().split('T')[0];
var address = row[2] ? String(row[2]).trim() : "";
var neighborhood = row[3] ? String(row[3]).trim() : "";
var cpf = row[4] ? String(row[4]).trim() : "";
var contact = row[5] ? String(row[5]).trim() : "";
var emergency = row[6] ? String(row[6]).trim() : "";
var allergyRaw = row[7] ? String(row[7]).trim() : "Não";
var allergy = "Não";
var allergyDetails = "";
var allergyRawLower = allergyRaw.toLowerCase();
if (allergyRawLower !== "não" && allergyRawLower !== "nao" && allergyRawLower !== "" && allergyRawLower !== "não " && allergyRawLower !== "nao ") {
allergy = "Sim";
allergyDetails = allergyRaw;
}
var payRaw = row[8] ? String(row[8]).toLowerCase() : "";
var paymentMethod = "PIX";
if (payRaw.indexOf("dinheiro") !== -1) {
paymentMethod = "Dinheiro";
} else if (payRaw.indexOf("cartão") !== -1 || payRaw.indexOf("cartao") !== -1 || payRaw.indexOf("crédito") !== -1 || payRaw.indexOf("credito") !== -1) {
paymentMethod = "Cartão";
}
registrations.push({
id: "sheet-camp-" + r,
name: name,
email: "",
address: address,
neighborhood: neighborhood,
cpf: cpf,
contact: contact,
allergy: allergy,
allergyDetails: allergyDetails,
paymentMethod: paymentMethod,
date: dateStr,
status: "Confirmado",
updatedAt: new Date(2000, 0, 1).toISOString()
});
}
}
} catch(e) {
Logger.log("Erro ao carregar inscrições do formulário: " + e.toString());
}
return registrations;
}
function getDatabaseFile() {
var files = DriveApp.getFilesByName(FILE_NAME);
var fileList = [];
while (files.hasNext()) {
fileList.push(files.next());
}
if (fileList.length === 0) {
return DriveApp.createFile(FILE_NAME, "{}", MimeType.PLAIN_TEXT);
}
var mainFile = fileList[0];
if (fileList.length > 1) {
var mergedData = {};
fileList.forEach(function(f) {
try {
var content = f.getAs("text/plain").getDataAsString();
var parsed = JSON.parse(content || "{}");
for (var key in parsed) {
if (Array.isArray(parsed[key])) {
if (!mergedData[key]) mergedData[key] = [];
mergedData[key] = mergedData[key].concat(parsed[key]);
} else if (typeof parsed[key] === 'object') {
if (!mergedData[key]) mergedData[key] = {};
for (var subKey in parsed[key]) {
mergedData[key][subKey] = parsed[key][subKey];
}
} else {
mergedData[key] = parsed[key];
}
}
} catch(e) {}
});
var arrayKeys = ["events", "notices", "campRegistrations", "leaders", "finance", "members"];
arrayKeys.forEach(function(key) {
if (Array.isArray(mergedData[key])) {
var seen = {};
mergedData[key] = mergedData[key].filter(function(item) {
if (!item) return false;
var id = item.id || item.username;
if (!id || seen[id]) return false;
seen[id] = true;
return true;
});
}
});
mainFile.setContent(JSON.stringify(mergedData));
for (var i = 1; i < fileList.length; i++) {
fileList[i].setTrashed(true);
}
}
return mainFile;
}
function doGet(e) {
var file = getDatabaseFile();
var content = file.getAs("text/plain").getDataAsString();
var data = {};
try { data = JSON.parse(content || "{}"); } catch (err) {}
var sheetFinance = getGoogleSheetFinance();
if (sheetFinance.length > 0) {
var existingFinance = data.finance || [];
data.finance = existingFinance.concat(sheetFinance);
}
var sheetCamp = getGoogleSheetCampRegistrations();
if (sheetCamp.length > 0) {
var existingCamp = data.campRegistrations || [];
var filteredCamp = existingCamp.filter(function(r) { return String(r.id).indexOf("sheet-") !== 0; });
data.campRegistrations = filteredCamp.concat(sheetCamp);
}
// Debug spreadsheet columns A,B,C,D,E,F
var debugSheet = {};
try {
var ss = SpreadsheetApp.openById(SPREADSHEET_ID);
var sheet = getFinanceSheet(ss);
if (sheet) {
var vals = sheet.getDataRange().getValues();
debugSheet.rowCount = vals.length;
debugSheet.colCount = vals.length > 0 ? vals[0].length : 0;
debugSheet.firstRows = vals.slice(0, Math.min(15, vals.length)).map(function(row) {
return row.slice(0, Math.min(8, row.length)).map(function(c) {
if (c instanceof Date) return c.toISOString();
return String(c);
});
});
} else {
debugSheet.error = "Aba não encontrada";
}
} catch(e) {
debugSheet.error = e.toString();
}
data.debugSheet = debugSheet;
// Debug Form Responses sheet columns
var debugFormSheet = {};
try {
var formSs = SpreadsheetApp.openById("1RNu6Iege7MMo6D5-R-oAbzwZqpWBD_5lx4Gdzqv-jmI");
var formSheets = formSs.getSheets();
var formSheet = formSs.getSheets()[0];
for (var i = 0; i < formSheets.length; i++) {
if (formSheets[i].getSheetId() == 1034041356) {
formSheet = formSheets[i];
break;
}
}
if (formSheet) {
var formVals = formSheet.getDataRange().getValues();
debugFormSheet.rowCount = formVals.length;
debugFormSheet.colCount = formVals.length > 0 ? formVals[0].length : 0;
debugFormSheet.firstRows = formVals.slice(0, Math.min(10, formVals.length)).map(function(row) {
return row.slice(0, Math.min(12, row.length)).map(function(c) {
if (c instanceof Date) return c.toISOString();
return String(c);
});
});
} else {
debugFormSheet.error = "Aba de respostas não encontrada";
}
} catch(e) {
debugFormSheet.error = e.toString();
}
data.debugFormSheet = debugFormSheet;
return ContentService.createTextOutput(JSON.stringify(data)).setMimeType(ContentService.MimeType.JSON);
}
function doPost(e) {
var lock = LockService.getScriptLock();
try {
lock.waitLock(10000);
} catch (err) {
return ContentService.createTextOutput(JSON.stringify({ status: "error", message: "Timeout" })).setMimeType(ContentService.MimeType.JSON);
}
var incomingData = JSON.parse(e.postData.contents);
// 1. Process deletions in the spreadsheet
var deletedIds = incomingData.deletedIds || [];
var finRowsToDelete = [];
var campRowsToDelete = [];
deletedIds.forEach(function(id) {
if (String(id).indexOf("sheet-camp-") === 0) {
var parts = id.split("-");
var rowNum = parseInt(parts[parts.length - 1]);
if (!isNaN(rowNum) && campRowsToDelete.indexOf(rowNum) === -1) {
campRowsToDelete.push(rowNum);
}
} else if (String(id).indexOf("sheet-ent-") === 0 || String(id).indexOf("sheet-sai-") === 0 || String(id).indexOf("sheet-row-") === 0) {
var parts = id.split("-");
var rowNum = parseInt(parts[parts.length - 1]);
if (!isNaN(rowNum) && finRowsToDelete.indexOf(rowNum) === -1) {
finRowsToDelete.push(rowNum);
}
}
});
if (finRowsToDelete.length > 0) {
try {
var ss = SpreadsheetApp.openById(SPREADSHEET_ID);
var sheet = getFinanceSheet(ss);
if (sheet) {
finRowsToDelete.sort(function(a, b) { return b - a; });
finRowsToDelete.forEach(function(r) {
if (r > 1 && r <= sheet.getLastRow()) {
sheet.deleteRow(r);
}
});
}
} catch(err) {
Logger.log("Erro ao excluir linhas da planilha de finanças: " + err.toString());
}
}
if (campRowsToDelete.length > 0) {
try {
var ss = SpreadsheetApp.openById(FORM_SPREADSHEET_ID);
var sheet = ss.getSheets()[0];
if (sheet) {
campRowsToDelete.sort(function(a, b) { return b - a; });
campRowsToDelete.forEach(function(r) {
if (r > 1 && r <= sheet.getLastRow()) {
sheet.deleteRow(r);
}
});
}
} catch(err) {
Logger.log("Erro ao excluir linhas da planilha do acampamento: " + err.toString());
}
}
// 2. Append new local finance records (IDs not starting with "sheet-") to the Google Sheet
if (incomingData.finance) {
try {
var ss = SpreadsheetApp.openById(SPREADSHEET_ID);
var sheet = getFinanceSheet(ss);
if (sheet) {
var dataRange = sheet.getDataRange();
var dataValues = dataRange.getValues();
var headerRowIdx = 0;
for (var r = 0; r < Math.min(10, dataValues.length); r++) {
var rowCells = dataValues[r].map(function(c) { return String(c).trim().toLowerCase(); });
if (rowCells.indexOf("data") !== -1 || rowCells.indexOf("descrição") !== -1 || rowCells.indexOf("descricao") !== -1 || rowCells.indexOf("receita") !== -1 || rowCells.indexOf("despesa") !== -1) {
headerRowIdx = r;
break;
}
}
var headers = dataValues.length > 0 ? dataValues[headerRowIdx].map(function(h) { return String(h).trim().toLowerCase(); }) : [];
var dateIdx = headers.indexOf("data") !== -1 ? headers.indexOf("data") : 0;
var descIdx = headers.indexOf("descrição") !== -1 ? headers.indexOf("descrição") :
headers.indexOf("descricao") !== -1 ? headers.indexOf("descricao") :
headers.indexOf("nome") !== -1 ? headers.indexOf("nome") : 1;
var tipoIdx = headers.indexOf("tipo") !== -1 ? headers.indexOf("tipo") : -1;
var entradaIdx = headers.indexOf("entrada") !== -1 ? headers.indexOf("entrada") :
headers.indexOf("entradas") !== -1 ? headers.indexOf("entradas") :
headers.indexOf("receita") !== -1 ? headers.indexOf("receita") :
headers.indexOf("receitas") !== -1 ? headers.indexOf("receitas") : 3;
var saidaIdx = headers.indexOf("saída") !== -1 ? headers.indexOf("saída") :
headers.indexOf("saida") !== -1 ? headers.indexOf("saida") :
headers.indexOf("saídas") !== -1 ? headers.indexOf("saídas") :
headers.indexOf("despesa") !== -1 ? headers.indexOf("despesa") :
headers.indexOf("despesas") !== -1 ? headers.indexOf("despesas") :
headers.indexOf("dispesa") !== -1 ? headers.indexOf("dispesa") :
headers.indexOf("dispesas") !== -1 ? headers.indexOf("dispesas") : 4;
// If sheet is completely empty or headers are missing, self-initialize row 1
if (dataValues.length === 0 || headers.length === 0 || dateIdx === -1 || entradaIdx === -1) {
sheet.getRange(1, 1, 1, 5).setValues([["Data", "Descrição", "Tipo", "Entrada (Receita)", "Saída (Despesa)"]]);
headers = ["data", "descrição", "tipo", "entrada (receita)", "saída (despesa)"];
dateIdx = 0;
descIdx = 1;
tipoIdx = 2;
entradaIdx = 3;
saidaIdx = 4;
}
incomingData.finance.forEach(function(rec) {
if (rec && rec.id && String(rec.id).indexOf("sheet-") !== 0) {
var rowData = [];
var maxIdx = Math.max(dateIdx, descIdx, tipoIdx, entradaIdx, saidaIdx);
for (var k = 0; k <= maxIdx; k++) rowData.push("");
// Format date if needed
var dVal = rec.date;
if (dVal && dVal.indexOf("-") !== -1) {
var p = dVal.split("-");
if (p.length === 3) {
// In Brazil, sheets usually prefer DD/MM/YYYY
dVal = p[2] + "/" + p[1] + "/" + p[0];
}
}
rowData[dateIdx] = dVal;
rowData[descIdx] = rec.name;
if (tipoIdx !== -1) {
rowData[tipoIdx] = rec.type;
}
var isSaida = (rec.type === 'Saída' || rec.type === 'Despesa');
if (isSaida) {
if (entradaIdx !== -1) rowData[entradaIdx] = "";
if (saidaIdx !== -1) rowData[saidaIdx] = rec.value;
} else {
if (entradaIdx !== -1) rowData[entradaIdx] = rec.value;
if (saidaIdx !== -1) rowData[saidaIdx] = "";
}
sheet.appendRow(rowData);
}
});
// 3. Write summary formulas in columns F, G, H (rows 2 and 3)
// Row 2: Headers
sheet.getRange("F2").setValue("Total Receitas");
sheet.getRange("G2").setValue("Total Despesas");
sheet.getRange("H2").setValue("Saldo Disponível");
// Find last transaction row (ignoring blank and summary rows at the bottom)
var lastTxRow = 1;
var vals = sheet.getDataRange().getValues();
for (var i = vals.length - 1; i >= 0; i--) {
var descVal = descIdx < vals[i].length ? String(vals[i][descIdx]).trim() : "";
if (descVal) {
var descValLower = descVal.toLowerCase();
if (descValLower.indexOf("total") === -1 && descValLower.indexOf("saldo") === -1 && descValLower.indexOf("caixa") === -1 && descValLower.indexOf("subtotal") === -1) {
lastTxRow = i + 1; // 1-based row number
break;
}
}
}
// Row 3: Formulas summing up to lastTxRow to avoid circular summation
var entColLetter = String.fromCharCode(65 + entradaIdx);
var saiColLetter = String.fromCharCode(65 + saidaIdx);
sheet.getRange("F3").setFormula("=SUM(" + entColLetter + "2:" + entColLetter + lastTxRow + ")");
sheet.getRange("G3").setFormula("=SUM(" + saiColLetter + "2:" + saiColLetter + lastTxRow + ")");
sheet.getRange("H3").setFormula("=F3-G3");
}
} catch(err) {
Logger.log("Erro ao salvar novos lançamentos na planilha: " + err.toString());
}
}
// Clean finance array before saving to JSON file (we don't save sheet- items or the new local items that were already appended)
if (incomingData.finance) {
incomingData.finance = [];
}
var file = getDatabaseFile();
var existingContent = file.getAs("text/plain").getDataAsString();
var existingData = {};
try { existingData = JSON.parse(existingContent || "{}"); } catch (err) {}
var mergedData = {};
var arrayKeys = ["events", "notices", "campRegistrations", "leaders", "finance", "members"];
var getTimestamp = function(item) {
if (!item || !item.updatedAt) return 0;
var t = Date.parse(item.updatedAt);
return isNaN(t) ? 0 : t;
};
arrayKeys.forEach(function(key) {
var existingArr = existingData[key] || [];
var incomingArr = incomingData[key] || [];
var deletedIds = incomingData.deletedIds || [];
var map = {};
existingArr.forEach(function(item) {
if (item && (item.id || item.username)) {
var id = item.id || item.username;
if (key === 'leaders' && item.username) {
id = 'leader-' + String(item.username).toLowerCase();
item.id = id;
}
map[id] = item;
}
});
incomingArr.forEach(function(item) {
if (item && (item.id || item.username)) {
var id = item.id || item.username;
if (key === 'leaders' && item.username) {
id = 'leader-' + String(item.username).toLowerCase();
item.id = id;
}
if (map[id]) {
var existingTime = getTimestamp(map[id]);
var incomingTime = getTimestamp(item);
if (incomingTime >= existingTime) {
map[id] = item;
}
} else {
map[id] = item;
}
}
});
deletedIds.forEach(function(id) {
delete map[id];
});
var mergedArr = [];
for (var id in map) { mergedArr.push(map[id]); }
mergedData[key] = mergedArr;
});
var existingCats = existingData.categories || [];
var incomingCats = incomingData.categories || [];
var catMap = {};
existingCats.forEach(function(c) { catMap[c] = true; });
incomingCats.forEach(function(c) { catMap[c] = true; });
var deletedIds = incomingData.deletedIds || [];
deletedIds.forEach(function(id) { delete catMap[id]; });
var mergedCats = [];
for (var cat in catMap) { mergedCats.push(cat); }
mergedData.categories = mergedCats;
var otherKeys = ["scale", "devotional"];
otherKeys.forEach(function(key) {
var existingItem = existingData[key] || {};
var incomingItem = incomingData[key] || {};
var existingTime = getTimestamp(existingItem);
var incomingTime = getTimestamp(incomingItem);
if (incomingTime >= existingTime) {
mergedData[key] = incomingItem;
} else {
mergedData[key] = existingItem;
}
});
if (incomingData.playlistUrl !== undefined) {
mergedData.playlistUrl = incomingData.playlistUrl;
} else if (existingData.playlistUrl !== undefined) {
mergedData.playlistUrl = existingData.playlistUrl;
}
var existingDeleted = existingData.deletedIds || [];
var incomingDeleted = incomingData.deletedIds || [];
var delMap = {};
existingDeleted.forEach(function(id) { delMap[id] = true; });
incomingDeleted.forEach(function(id) { delMap[id] = true; });
var mergedDeleted = [];
for (var id in delMap) { mergedDeleted.push(id); }
mergedData.deletedIds = mergedDeleted;
file.setContent(JSON.stringify(mergedData));
lock.releaseLock();
var sheetFinance = getGoogleSheetFinance();
if (sheetFinance.length > 0) {
var existingFinance = mergedData.finance || [];
mergedData.finance = existingFinance.concat(sheetFinance);
}
var sheetCamp = getGoogleSheetCampRegistrations();
if (sheetCamp.length > 0) {
var existingCamp = mergedData.campRegistrations || [];
var filteredCamp = existingCamp.filter(function(r) { return String(r.id).indexOf("sheet-") !== 0; });
mergedData.campRegistrations = filteredCamp.concat(sheetCamp);
}
return ContentService.createTextOutput(JSON.stringify({ status: "success", data: mergedData })).setMimeType(ContentService.MimeType.JSON);
}
- Clique em Implantar > Nova implantação (no topo direito).
- No ícone de engrenagem, selecione App da Web.
- Configure:
- Executar como: Eu (seu-email@gmail.com)
- Quem tem acesso: Qualquer pessoa
- Clique em Implantar e autorize as permissões da sua conta.
- Copie o link gerado em App da Web (URL) e cole no campo acima!
Cadastrar Novo Líder
Líderes Cadastrados
Inscrições do Acampamento
0
Total Inscritos
0
Confirmados (Pago)
0
Pendentes
R$ 0
Total Caixa
Resumo de Vagas 📊
Preenchimento (Meta: 60 vagas)
0/60 (0%)
Formas de Pagamento:
PIX: 0 | Dinheiro: 0
Alergias:
Nenhum registrado
Membros Cadastrados 👥
0
Total Membros
0
Menores de Idade
Meus Sermões & Esboços 📖
Copie o esboço gerado no Gemini Pro, cole aqui e organize-os por culto e data para consultas rápidas.