const CONFIG = {
BASE_URL: "https://flowpro.ma",
ENDPOINTS: {
SINGLE_ROW: "/api/receive-data",
BULK_DATA: "/api/receive-bulk-data"
},
TIMEOUT: 30000,
RETRY_COUNT: 3
};
function getUserCode() {
try {
var sheet = SpreadsheetApp.getActiveSheet();
var code = sheet.getRange("A1").getValue();
if (!code || code === "") {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ ضع كودك في A1", "كود مفقود", 5);
return null;
}
return String(code).toUpperCase().trim();
} catch (error) {
Logger.log("❌ خطأ: " + error.message);
return null;
}
}
function sendRowToServer(e) {
if (!e || !e.range) return;
var sheet = e.source.getActiveSheet();
var row = e.range.getRow();
if (row === 1 || row === 2) return;
var userCode = getUserCode();
if (!userCode) return;
try {
var lastColumn = sheet.getLastColumn();
var headers = sheet.getRange(2, 1, 1, lastColumn).getValues()[0];
var rowData = sheet.getRange(row, 1, 1, lastColumn).getValues()[0];
if (rowData.every(cell => cell === "" || cell == null)) return;
var structuredData = {};
for (var i = 0; i < headers.length; i++) {
var columnName = headers[i] || `column_${i + 1}`;
var cellValue = rowData[i];
structuredData[columnName] = cellValue instanceof Date ? cellValue.toISOString() : cellValue;
}
var payload = {
user_code: userCode,
row_number: row,
sheet_name: sheet.getName(),
headers: headers,
structured_data: structuredData,
timestamp: new Date().toISOString(),
spreadsheet_id: SpreadsheetApp.getActiveSpreadsheet().getId()
};
sendWithRetry(CONFIG.BASE_URL + CONFIG.ENDPOINTS.SINGLE_ROW, payload, function(success, response) {
if (success) {
SpreadsheetApp.getActiveSpreadsheet().toast("✅ الصف " + row + " تم إرساله", "نجح", 2);
} else {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ فشل الصف " + row, "خطأ", 5);
}
});
} catch (error) {
Logger.log("❌ خطأ: " + error.message);
}
}
function sendAllData() {
var userCode = getUserCode();
if (!userCode) return;
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
if (lastRow < 3) {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ لا توجد بيانات", "تحذير", 3);
return;
}
try {
var headers = sheet.getRange(2, 1, 1, lastColumn).getValues()[0];
var allData = [];
for (var row = 3; row <= lastRow; row++) {
var rowData = sheet.getRange(row, 1, 1, lastColumn).getValues()[0];
if (rowData.every(cell => cell === "" || cell == null)) continue;
var structuredData = {};
for (var i = 0; i < headers.length; i++) {
var columnName = headers[i] || `column_${i + 1}`;
var cellValue = rowData[i];
structuredData[columnName] = cellValue instanceof Date ? cellValue.toISOString() : cellValue;
}
allData.push({
row_number: row,
structured_data: structuredData
});
}
if (allData.length === 0) {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ لا توجد بيانات صحيحة", "تحذير", 3);
return;
}
var payload = {
user_code: userCode,
sheet_name: sheet.getName(),
headers: headers,
total_rows: allData.length,
data: allData,
timestamp: new Date().toISOString(),
spreadsheet_id: SpreadsheetApp.getActiveSpreadsheet().getId()
};
sendWithRetry(CONFIG.BASE_URL + CONFIG.ENDPOINTS.BULK_DATA, payload, function(success, response) {
if (success) {
SpreadsheetApp.getActiveSpreadsheet().toast("✅ " + allData.length + " صف تم إرسالهم", "اكتمل", 4);
} else {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ فشل الإرسال", "خطأ", 5);
}
});
} catch (error) {
Logger.log("❌ خطأ: " + error.message);
}
}
function sendWithRetry(url, payload, callback, attempt) {
attempt = attempt || 1;
try {
var options = {
method: "POST",
contentType: "application/json",
payload: JSON.stringify(payload),
muteHttpExceptions: true,
timeout: CONFIG.TIMEOUT
};
var response = UrlFetchApp.fetch(url, options);
var responseCode = response.getResponseCode();
var responseText = response.getContentText();
if (responseCode >= 200 && responseCode < 300) {
callback(true, responseText);
} else if (attempt < CONFIG.RETRY_COUNT) {
Utilities.sleep(Math.pow(2, attempt) * 1000);
sendWithRetry(url, payload, callback, attempt + 1);
} else {
callback(false, `HTTP ${responseCode}: ${responseText}`);
}
} catch (error) {
if (attempt < CONFIG.RETRY_COUNT) {
Utilities.sleep(Math.pow(2, attempt) * 1000);
sendWithRetry(url, payload, callback, attempt + 1);
} else {
callback(false, error.message);
}
}
}
function testConnection() {
try {
var response = UrlFetchApp.fetch(CONFIG.BASE_URL + "/api/sheets", {
method: "GET",
muteHttpExceptions: true,
timeout: 15000
});
var responseCode = response.getResponseCode();
var message = responseCode >= 200 && responseCode < 300 ? "✅ الاتصال نجح!" : "⚠️ خطأ: " + responseCode;
SpreadsheetApp.getActiveSpreadsheet().toast(message, "اختبار الاتصال", 4);
Logger.log("✅ نتيجة: " + responseCode);
} catch (error) {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ فشل الاتصال", "خطأ", 5);
Logger.log("❌ خطأ: " + error.message);
}
}
function createTrigger() {
deleteTriggers();
try {
ScriptApp.newTrigger("sendRowToServer").forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet()).onEdit().create();
SpreadsheetApp.getActiveSpreadsheet().toast("✅ تم إنشاء المشغل", "جاهز", 3);
Logger.log("✅ تم إنشاء المشغل بنجاح");
} catch (error) {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ فشل إنشاء المشغل", "خطأ", 5);
Logger.log("❌ خطأ: " + error.message);
}
}
function deleteTriggers() {
var triggers = ScriptApp.getProjectTriggers();
var deletedCount = 0;
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === "sendRowToServer") {
ScriptApp.deleteTrigger(triggers[i]);
deletedCount++;
}
}
if (deletedCount > 0) {
Logger.log("✅ تم حذف " + deletedCount + " مشغل(ات)");
}
}
function verifySetup() {
var sheet = SpreadsheetApp.getActiveSheet();
var code = sheet.getRange("A1").getValue();
var headers = sheet.getRange("2:2").getValues()[0];
var dataRowCount = sheet.getLastRow() - 2;
var message = "📋 التحقق:\n\n";
message += code ? "✅ الكود: " + code + "\n" : "❌ لا يوجد كود\n";
message += headers.length > 0 ? "✅ رؤوس موجودة\n" : "❌ لا توجد رؤوس\n";
message += dataRowCount > 0 ? "✅ " + dataRowCount + " صف\n" : "⚠️ لا توجد بيانات\n";
SpreadsheetApp.getActiveSpreadsheet().toast(message, "حالة الإعداد", 6);
Logger.log(message);
}
function quickSetup() {
Logger.log("════════════════════════════════════════");
Logger.log("🔧 بدء الإعداد السريع");
Logger.log("════════════════════════════════════════");
var userCode = getUserCode();
if (!userCode) {
SpreadsheetApp.getActiveSpreadsheet().toast("❌ أضف كودك في A1 أولاً!", "لا يمكن الإعداد", 5);
return;
}
SpreadsheetApp.getActiveSpreadsheet().toast("🔧 جاري الإعداد...", "إعداد", 2);
Logger.log("📍 رابط الخادم: " + CONFIG.BASE_URL);
Logger.log("🔑 كود المستخدم: " + userCode);
Utilities.sleep(1000);
testConnection();
Utilities.sleep(2000);
createTrigger();
SpreadsheetApp.getActiveSpreadsheet().toast("🎉 اكتمل الإعداد بنجاح!", "جاهز", 4);
Logger.log("════════════════════════════════════════");
Logger.log("✅ انتهى الإعداد السريع!");
Logger.log("════════════════════════════════════════");
}
function simpleTest() {
Logger.log("✅ الكود يعمل!");
SpreadsheetApp.getActiveSpreadsheet().toast("✅ الكود يعمل بنجاح!", "اختبار", 3);
}
Enregistrer