Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions FolderManagement.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Folder Management Library
* Handles creation and management of student folders with company ID support
*/

/**
* Creates folder manager instance
*/
function createFolderManager(config) {
return {
createStudentFolders: function(studentData) {
const results = {};

try {
// Format student identifiers
const formattedId = studentData.studentId.toString().padStart(4, '0');
const formattedName = studentData.name.toLowerCase().replace(/\s+/g, '_');
const folderName = `${studentData.companyId}+${formattedId}+${formattedName}`;

// Create main folder structure
const companyFolder = DriveApp.getFolderById(config.COMPANIES_ROOT_ID);
const mainFolder = companyFolder.createFolder(folderName);
results.mainFolderId = mainFolder.getId();

// Create subfolders
const subfolders = ['slides', 'forms', 'sheets', 'docs', 'drive', 'gmail'];
subfolders.forEach(subfolder => {
const newFolder = mainFolder.createFolder(subfolder);
results[`${subfolder}FolderId`] = newFolder.getId();
});

return results;

} catch (error) {
throw new Error(`Failed to create folders: ${error.message}`);
}
}
};
}
65 changes: 65 additions & 0 deletions LogsManagement.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Logs Management Library
* Handles logging of operations with company ID support
*/

/**
* Creates logs manager instance
*/
function createLogsManager(config) {
return {
logSuccess: function(studentData, folderIds, spreadsheetId) {
try {
const spreadsheet = SpreadsheetApp.openById(config.CONTROL_SPREADSHEET_ID);
const sheet = spreadsheet.getActiveSheet();

const formattedId = studentData.studentId.toString().padStart(4, '0');
const formattedName = studentData.name.toLowerCase().replace(/\s+/g, '_');

const row = [
new Date(),
studentData.companyId,
formattedId,
formattedName,
studentData.email,
studentData.batch,
folderIds.mainFolderId,
spreadsheetId,
'Success'
];

sheet.appendRow(row);

} catch (error) {
console.error(`Failed to log success: ${error.message}`);
}
},

logError: function(studentData, error) {
try {
const spreadsheet = SpreadsheetApp.openById(config.CONTROL_SPREADSHEET_ID);
const sheet = spreadsheet.getActiveSheet();

const formattedId = studentData.studentId.toString().padStart(4, '0');
const formattedName = studentData.name.toLowerCase().replace(/\s+/g, '_');

const row = [
new Date(),
studentData.companyId,
formattedId,
formattedName,
studentData.email,
studentData.batch,
'',
'',
`Error: ${error.message}`
];

sheet.appendRow(row);

} catch (logError) {
console.error(`Failed to log error: ${logError.message}`);
}
}
};
}
38 changes: 38 additions & 0 deletions SpreadsheetManagement.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Spreadsheet Management Library
* Handles creation and management of student spreadsheets with company ID support
*/

/**
* Creates spreadsheet manager instance
*/
function createSpreadsheetManager(config) {
return {
createStudentSpreadsheet: function(studentData) {
try {
// Format student identifiers
const formattedId = studentData.studentId.toString().padStart(4, '0');
const formattedName = studentData.name.toLowerCase().replace(/\s+/g, '_');
const spreadsheetName = `${studentData.companyId}+${formattedId}+${formattedName}_scores`;

// Create spreadsheet in company admin folder
const folder = DriveApp.getFolderById(config.COMPANY_ADMIN_ID);
const spreadsheet = SpreadsheetApp.create(spreadsheetName);
const file = DriveApp.getFileById(spreadsheet.getId());

// Move to correct folder
file.moveTo(folder);

// Set up initial structure
const sheet = spreadsheet.getActiveSheet();
sheet.setName('Scores');
sheet.getRange('A1:D1').setValues([['Task', 'Score', 'Date', 'Comments']]);

return spreadsheet.getId();

} catch (error) {
throw new Error(`Failed to create spreadsheet: ${error.message}`);
}
}
};
}
47 changes: 47 additions & 0 deletions TaskSharingManagement.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Task Sharing Management Library
* Handles task assignments and permissions with company ID support
*/

/**
* Creates task manager instance
*/
function createTaskManager(config) {
return {
setupStudentTasks: function(studentData, folderIds) {
try {
// Validate company ID format
if (!config.COMPANY_ID_REGEX.test(studentData.companyId)) {
throw new Error('Invalid company ID format');
}

// Format student identifiers
const formattedId = studentData.studentId.toString().padStart(4, '0');
const formattedName = studentData.name.toLowerCase().replace(/\s+/g, '_');

// Set permissions on folders
Object.values(folderIds).forEach(folderId => {
const folder = DriveApp.getFolderById(folderId);
folder.addEditor(studentData.email);
});

// Copy and share task templates
const taskFolder = DriveApp.getFolderById(config.TASK_PDFS_ID);
const targetFolder = DriveApp.getFolderById(folderIds.mainFolderId);

const files = taskFolder.getFiles();
while (files.hasNext()) {
const file = files.next();
const newFile = file.makeCopy(targetFolder);
newFile.setName(`${studentData.companyId}+${formattedId}+${file.getName()}`);
newFile.addViewer(studentData.email);
}

return true;

} catch (error) {
throw new Error(`Failed to setup tasks: ${error.message}`);
}
}
};
}
188 changes: 188 additions & 0 deletions main.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/**
* Main configuration and setup script
*/

const CONFIG = {
// Company Information
COMPANY_NAME: 'Example Company',
COMPANY_ID: 'C001', // Company ID in C### format
COMPANY_ID_REGEX: /^C\d{3}$/, // Validation pattern for company IDs

// Root folder IDs
TRAINING_ROOT_ID: '1XkaQRv7rwmM36QpFEzz5e_t6E5j3xG68',
COMPANIES_ROOT_ID: '19ilsru6jV9Oj9Vv5OJzwj9SWTWjci0yZ',

// Company specific folder IDs
COMPANY_ADMIN_ID: '1csCqCxGa-8Res896uYsKKjVBOEP_ZSQJ',
TRAINER_ADMIN_ID: '1qynN7ZRDttPaaaN-jOHwGg7Q0vaHgFrO',

// Assignment folders
ASSIGNMENT_MASTER_ID: '1iEi0ApNrECvCJJBFxPPthcXFv6mjUiww',
TASK_PDFS_ID: '17qKubT2cmTsdwyFJPEz9tRaEzqqAEb0J',
TASK_RAW_DATA_ID: '1DJgwKVLx8aBbEqVkVvH6qcPlloZsw_n8',

// Spreadsheet IDs
STUDENT_DATABASE_ID: '1UDOOKV4pUlyKOHfwmyCq-AN31ryWAj9GHIokfZ_0swI',
CONTROL_SPREADSHEET_ID: '1yH_242vGvkM3vVmQK4SB-gizmEBgXMzMUb6TB-1BkKo'
};

/**
* Creates menu when spreadsheet opens
*/
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Training Setup')
.addItem('Initialize Setup', 'initializeSetup')
.addItem('Create Student Resources', 'createStudentResources')
.addToUi();
}

/**
* Initializes the setup by checking core requirements
*/
function initializeSetup() {
const results = [];
const errors = [];

try {
// Verify we're running from a shared drive
const activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const file = DriveApp.getFileById(activeSpreadsheet.getId());
const parents = file.getParents();

if (!parents.hasNext() || !parents.next().isShareableByEditors()) {
throw new Error('This script must be run from a shared drive');
}

// Verify company name and ID are set
if (!CONFIG.COMPANY_NAME) {
throw new Error('Company name must be set in CONFIG');
}
if (!CONFIG.COMPANY_ID || !CONFIG.COMPANY_ID_REGEX.test(CONFIG.COMPANY_ID)) {
throw new Error('Company ID must be set in CONFIG and match pattern C### (e.g., C001)');
}

// Verify critical folders exist
verifyFolderExists('Training Root', CONFIG.TRAINING_ROOT_ID, results, errors);
verifyFolderExists('Company Admin', CONFIG.COMPANY_ADMIN_ID, results, errors);
verifyFolderExists('Trainer Admin', CONFIG.TRAINER_ADMIN_ID, results, errors);
verifyFolderExists('Assignment Master', CONFIG.ASSIGNMENT_MASTER_ID, results, errors);
verifyFolderExists('Task PDFs', CONFIG.TASK_PDFS_ID, results, errors);
verifyFolderExists('Task Raw Data', CONFIG.TASK_RAW_DATA_ID, results, errors);

// Verify spreadsheets
verifySpreadsheetExists('Student Database', CONFIG.STUDENT_DATABASE_ID, results, errors);
verifySpreadsheetExists('Control Spreadsheet', CONFIG.CONTROL_SPREADSHEET_ID, results, errors);

displayResults('Setup Initialization', results, errors);
return errors.length === 0;

} catch (error) {
errors.push(`Setup failed: ${error.toString()}`);
displayResults('Setup Failed', results, errors);
return false;
}
}

/**
* Creates student resources based on database entries
*/
function createStudentResources() {
const results = [];
const errors = [];

try {
// Initialize managers
const folderManager = createFolderManager(CONFIG);
const spreadsheetManager = createSpreadsheetManager(CONFIG);
const taskManager = createTaskManager(CONFIG);
const logsManager = createLogsManager(CONFIG);

// Get student data from database
const studentData = getStudentData();

// Process each student
studentData.forEach(student => {
try {
// Create folders and resources
const folderIds = folderManager.createStudentFolders(student);
const spreadsheetId = spreadsheetManager.createStudentSpreadsheet(student);
const taskSetup = taskManager.setupStudentTasks(student, folderIds);

// Log successful creation
logsManager.logSuccess(student, folderIds, spreadsheetId);
results.push(`✓ Created resources for ${student.name}`);

} catch (error) {
errors.push(`Failed to process student ${student.name}: ${error.toString()}`);
logsManager.logError(student, error);
}
});

displayResults('Resource Creation', results, errors);

} catch (error) {
errors.push(`Setup failed: ${error.toString()}`);
displayResults('Setup Failed', results, errors);
}
}

/**
* Gets student data from database spreadsheet
*/
function getStudentData() {
const spreadsheet = SpreadsheetApp.openById(CONFIG.STUDENT_DATABASE_ID);
const sheet = spreadsheet.getActiveSheet();
const data = sheet.getDataRange().getValues();

// Remove header row and map to student objects
return data.slice(1).map(row => ({
companyId: CONFIG.COMPANY_ID,
studentId: row[0],
name: row[1],
email: row[2],
batch: row[3]
}));
}

/**
* Utility function to verify folder exists and is accessible
*/
function verifyFolderExists(name, id, results, errors) {
try {
DriveApp.getFolderById(id);
results.push(`✓ ${name} folder is accessible`);
} catch (error) {
errors.push(`❌ Cannot access ${name} folder: ${error.toString()}`);
}
}

/**
* Utility function to verify spreadsheet exists and is accessible
*/
function verifySpreadsheetExists(name, id, results, errors) {
try {
SpreadsheetApp.openById(id);
results.push(`✓ ${name} spreadsheet is accessible`);
} catch (error) {
errors.push(`❌ Cannot access ${name} spreadsheet: ${error.toString()}`);
}
}

/**
* Displays results in UI
*/
function displayResults(title, results, errors) {
const ui = SpreadsheetApp.getUi();
let message = '📋 Results:\n\n';

if (results.length > 0) {
message += '✅ Completed Successfully:\n' + results.join('\n') + '\n\n';
}

if (errors.length > 0) {
message += '❌ Issues Found:\n' + errors.join('\n');
}

ui.alert(title, message, ui.ButtonSet.OK);
}