Upload Code.gs
Browse files- apps-script/Code.gs +113 -0
apps-script/Code.gs
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const SPREADSHEET_ID = "18vKc9qAKo8htCipBXxr2Uy3zgYS_k3qlUdlAWkKMeIA";
|
| 2 |
+
const SHEET_NAME = "الورقة1";
|
| 3 |
+
const EDITABLE_HEADERS = ["الاسم", "المسمى الوظفي", "المسمى الوظيفي", "البريد الإلكتروني", "رقم التواصل"];
|
| 4 |
+
|
| 5 |
+
function doGet(e) {
|
| 6 |
+
return handleRequest_(e);
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
function doPost(e) {
|
| 10 |
+
return handleRequest_(e);
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
function handleRequest_(e) {
|
| 14 |
+
try {
|
| 15 |
+
const payload = parsePayload_(e);
|
| 16 |
+
const action = String(payload.action || e.parameter.action || "read").toLowerCase();
|
| 17 |
+
if (action === "read" || action === "getdata" || action === "list") {
|
| 18 |
+
return json_({ ok: true, ...readSheet_() });
|
| 19 |
+
}
|
| 20 |
+
if (action === "update" || action === "save") {
|
| 21 |
+
return json_(updateRow_(payload));
|
| 22 |
+
}
|
| 23 |
+
return json_({ ok: false, message: "إجراء غير معروف." });
|
| 24 |
+
} catch (error) {
|
| 25 |
+
return json_({ ok: false, message: error.message || String(error) });
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
function parsePayload_(e) {
|
| 30 |
+
if (!e) return {};
|
| 31 |
+
if (e.postData && e.postData.contents) {
|
| 32 |
+
try {
|
| 33 |
+
return JSON.parse(e.postData.contents);
|
| 34 |
+
} catch (error) {
|
| 35 |
+
if (e.parameter && e.parameter.payload) {
|
| 36 |
+
return JSON.parse(e.parameter.payload);
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
if (e.parameter && e.parameter.payload) {
|
| 41 |
+
return JSON.parse(e.parameter.payload);
|
| 42 |
+
}
|
| 43 |
+
return e.parameter || {};
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
function getSheet_() {
|
| 47 |
+
const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
|
| 48 |
+
const sheet = spreadsheet.getSheetByName(SHEET_NAME) || spreadsheet.getSheets()[0];
|
| 49 |
+
if (!sheet) throw new Error("لم يتم العثور على ورقة بيانات داخل Google Sheet.");
|
| 50 |
+
return sheet;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
function readSheet_() {
|
| 54 |
+
const sheet = getSheet_();
|
| 55 |
+
const lastRow = sheet.getLastRow();
|
| 56 |
+
const lastColumn = sheet.getLastColumn();
|
| 57 |
+
if (lastRow < 1 || lastColumn < 1) {
|
| 58 |
+
return { sheetName: sheet.getName(), headers: [], rows: [] };
|
| 59 |
+
}
|
| 60 |
+
const values = sheet.getRange(1, 1, lastRow, lastColumn).getDisplayValues();
|
| 61 |
+
const headers = values[0].map((header) => String(header || "").trim());
|
| 62 |
+
const rows = values.slice(1)
|
| 63 |
+
.map((row, index) => {
|
| 64 |
+
const item = { rowNumber: index + 2 };
|
| 65 |
+
headers.forEach((header, columnIndex) => {
|
| 66 |
+
if (header) item[header] = row[columnIndex] || "";
|
| 67 |
+
});
|
| 68 |
+
return item;
|
| 69 |
+
})
|
| 70 |
+
.filter((row) => headers.some((header) => header && String(row[header] || "").trim()));
|
| 71 |
+
return { sheetName: sheet.getName(), headers, rows };
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
function updateRow_(payload) {
|
| 75 |
+
const sheet = getSheet_();
|
| 76 |
+
const data = readSheet_();
|
| 77 |
+
const headers = data.headers;
|
| 78 |
+
const headerIndex = {};
|
| 79 |
+
headers.forEach((header, index) => {
|
| 80 |
+
headerIndex[header] = index + 1;
|
| 81 |
+
});
|
| 82 |
+
|
| 83 |
+
const rowNumber = Number(payload.rowNumber || payload.rowIndex);
|
| 84 |
+
if (!rowNumber || rowNumber < 2 || rowNumber > sheet.getLastRow()) {
|
| 85 |
+
throw new Error("رقم الصف غير صحيح، ولن يتم إنشاء صف جديد.");
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
const updates = typeof payload.updates === "string" ? JSON.parse(payload.updates) : (payload.updates || {});
|
| 89 |
+
const allowedColumns = Object.keys(updates).filter((header) => {
|
| 90 |
+
return EDITABLE_HEADERS.indexOf(header) !== -1 && headerIndex[header];
|
| 91 |
+
});
|
| 92 |
+
if (!allowedColumns.length) {
|
| 93 |
+
throw new Error("لا توجد أعمدة مسموح بتحديثها في الطلب.");
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
allowedColumns.forEach((header) => {
|
| 97 |
+
sheet.getRange(rowNumber, headerIndex[header]).setValue(updates[header] || "");
|
| 98 |
+
});
|
| 99 |
+
|
| 100 |
+
return {
|
| 101 |
+
ok: true,
|
| 102 |
+
success: true,
|
| 103 |
+
rowNumber,
|
| 104 |
+
updatedHeaders: allowedColumns,
|
| 105 |
+
message: "تم تحديث الصف نفسه بنجاح.",
|
| 106 |
+
};
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
function json_(payload) {
|
| 110 |
+
return ContentService
|
| 111 |
+
.createTextOutput(JSON.stringify(payload))
|
| 112 |
+
.setMimeType(ContentService.MimeType.JSON);
|
| 113 |
+
}
|