{"id":29225811,"url":"https://github.com/hetrox8/it-helpdesk-ticketing-system","last_synced_at":"2025-08-02T05:36:41.355Z","repository":{"id":297571607,"uuid":"996975643","full_name":"hetrox8/it-helpdesk-ticketing-system","owner":"hetrox8","description":"This project demonstrates how to wire together Google Workspace components (Form, Sheet, Apps Script) into a lightweight ticketing workflow. It’s ideal for small teams or as a stepping stone toward a more robust help-desk solution.","archived":false,"fork":false,"pushed_at":"2025-06-06T06:11:27.000Z","size":386,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-03T07:51:52.908Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hetrox8.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-05T18:48:34.000Z","updated_at":"2025-06-06T06:11:29.000Z","dependencies_parsed_at":"2025-06-06T07:32:33.642Z","dependency_job_id":null,"html_url":"https://github.com/hetrox8/it-helpdesk-ticketing-system","commit_stats":null,"previous_names":["hetrox8/it-helpdesk-ticketing-system"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hetrox8/it-helpdesk-ticketing-system","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hetrox8%2Fit-helpdesk-ticketing-system","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hetrox8%2Fit-helpdesk-ticketing-system/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hetrox8%2Fit-helpdesk-ticketing-system/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hetrox8%2Fit-helpdesk-ticketing-system/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hetrox8","download_url":"https://codeload.github.com/hetrox8/it-helpdesk-ticketing-system/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hetrox8%2Fit-helpdesk-ticketing-system/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268339412,"owners_count":24234545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-03T07:38:21.342Z","updated_at":"2025-08-02T05:36:41.319Z","avatar_url":"https://github.com/hetrox8.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IT Help Desk Ticketing System\n\n**A lightweight ticketing workflow built with Google Forms, Google Sheets, and Apps Script.**  \nWhenever a user submits a ticket via the Google Form, a unique Ticket ID is generated, an “Open” status is set, and an email notification is sent to IT support automatically.\n\n---\n# IT Help Desk Ticketing System\n\n[![Made with Google Apps Script](https://img.shields.io/badge/Built%20with-Apps%20Script-blue?logo=google)](https://developers.google.com/apps-script)\n[![Google Sheets](https://img.shields.io/badge/Google%20Sheets-Tracker-success?logo=googlesheets)](https://www.google.com/sheets/about/)\n[![Google Forms](https://img.shields.io/badge/Google%20Forms-Frontend-purple?logo=googleforms)](https://docs.google.com/forms/)\n[![MIT License](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n[![Project Status](https://img.shields.io/badge/status-Complete-brightgreen)]()\n\n**A lightweight ticketing workflow built with Google Forms, Google Sheets, and Apps Script.**  \nWhenever a user submits a ticket via the Google Form, a unique Ticket ID is generated, an “Open” status is set, and an email notification is sent to IT support automatically.\n\n## 📌 Table of Contents\n\n1. [Project Overview](#project-overview)  \n2. [Tools \u0026 Technologies](#tools--technologies)  \n3. [Setup Guide](#setup-guide)  \n   1. [1. Create the Google Form](#1-create-the-google-form)  \n   2. [2. Create \u0026 Structure the Google Sheet](#2-create--structure-the-google-sheet)  \n   3. [3. Apps Script (Code + Trigger)](#3-apps-script-code--trigger)  \n4. [Screenshots](#screenshots)  \n5. [Testing \u0026 Validation](#testing--validation)  \n6. [What I Learned](#what-i-learned)  \n7. [Future Enhancements](#future-enhancements)  \n8. [Repository Structure](#repository-structure)  \n\n---\n\n## Project Overview\n\n**Objective:** Build a simple, web-accessible ticketing system that:\n\n- Allows users to submit IT support requests via Google Form.  \n- Automatically generates a unique Ticket ID (e.g., `TKT-2025-001`).  \n- Records ticket details in a Google Sheet, including fields like Status, Priority, and Assigned To.  \n- Sends an email notification to the IT support inbox whenever a new ticket is submitted.\n\nThis project demonstrates how to wire together Google Workspace components (Form, Sheet, Apps Script) into a lightweight ticketing workflow. It’s ideal for small teams or as a stepping stone toward a more robust help-desk solution.\n\n---\n\n## Tools \u0026 Technologies\n\n- **Google Forms** (Front-end for ticket submission)  \n- **Google Sheets** (Backend database for tickets)  \n- **Google Apps Script** (Server-side scripting to generate IDs and send emails)  \n- **Gmail** (Used by Apps Script to send notification emails)  \n- (Optional) Any modern browser to create and test the Form/Sheet  \n\n---\n\n## Setup Guide\n\nBelow are the detailed steps to build and configure each component.\n\n### 1. Create the Google Form\n\n1. In Google Drive, click **New → Google Forms → Blank Form**.  \n2. Rename the form to:  \n3. (Optional) Under the form description, add a short instruction, e.g.:  \n\u003e Fill out this form to submit an IT support ticket. A confirmation email will be sent to you automatically.  \n4. Add the following questions (all **Required** unless noted):  \n1. **Full Name**  \n   - Type: Short answer  \n2. **Email Address**  \n   - Type: Short answer  \n   - Enable “Response validation” → “Text” → “Email address”  \n3. **Issue Category**  \n   - Type: Dropdown  \n   - Options:  \n     - Software  \n     - Hardware  \n     - Network  \n     - Access / Permissions  \n     - Other  \n4. **Priority**  \n   - Type: Dropdown  \n   - Options: Low, Medium, High  \n5. **Issue Description**  \n   - Type: Paragraph  \n6. **Attach Screenshot (optional)**  \n   - Type: File upload  \n   - Allowed file types: Images, Documents  \n7. **(Hidden)** We will add “Ticket ID” – *not visible on the Form itself* (handled in the Sheet/Apps Script).  \n\n\u003e **Form Settings:**  \n\u003e - Under ⚙️ Settings → **General**, you may turn on “Collect email addresses” so that Google automatically captures the user’s email. If you do this, you can skip the “Email Address” question.  \n\u003e - Under ⚙️ Settings → **Presentation**, you can uncheck “Show link to submit another response.”  \n\u003e - Click **Send** to get the Form’s URL (if you want to test manually from another device).\n\n---\n\n### 2. Create \u0026 Structure the Google Sheet\n\n1. In Google Drive, click **New → Google Sheets → Blank sheet**.  \n2. Rename the sheet (file name) to:  \n3. Link the Form to this Sheet:  \n1. Open your Form → go to the **Responses** tab → click the green Sheets icon.  \n2. Select **“Select existing spreadsheet”** → choose **Ticket Tracker**.  \n3. Google will populate Row 1 with default headers (e.g., `Timestamp`, `Full Name`, `Email Address`, etc.) as soon as you submit a test response.  \n4. Insert the following **new columns** (after “Timestamp”):  \n- **B: Ticket ID**  \n- **C: Status** (default value = “Open”)  \n- **D: Assigned To** (leave blank by default)  \n- **E: Last Updated** (timestamp of last update)  \n5. Shift the original Form-generated columns one position to the right, so your header row (Row 1) looks like this:\n\n| A: Timestamp | B: Ticket ID | C: Status | D: Assigned To | E: Last Updated | F: Full Name | G: Email Address | H: Issue Category | I: Priority | J: Issue Description | K: File Upload |\n| ------------ | ------------ | --------- | -------------- | ---------------- | ------------ | ---------------- | ----------------- | ----------- | -------------------- | --------------- |\n\n6. (Optional) Add **Data Validation** to the Status column (C):  \n- Select column C (click the “C” header).  \n- Go to **Data → Data validation**.  \n- Under “Criteria,” choose “List of items” and enter:  \n  ```\n  Open, In Progress, Resolved, Closed\n  ```  \n- Check “Show dropdown list in cell.” Click **Save**.  \n7. (Optional) Apply **Conditional Formatting** to highlight “High” priority:  \n- Select column I (Priority).  \n- Go to **Format → Conditional formatting**.  \n- Under “Format cells if…,” select “Text is exactly” and type `High`.  \n- Choose a light red fill. Click **Done**.  \n8. Freeze the header row:  \n- View → Freeze → 1 row.  \n\nAt this point, if you submit a dummy ticket via the Form, you should see one row of data appear. But columns B–E will be blank until we add Apps Script to populate them.\n\n---\n\n### 3. Apps Script (Code + Trigger)\n\n#### 3.1. Apps Script Code\n\n1. In your **Ticket Tracker** Sheet, navigate to:  \n2. In the Code Editor that opens, replace any default code in `Code.gs` with the following **entire** script:\n\n```javascript\n/**\n * Apps Script for IT Help Desk Ticketing System\n * ---------------------------------------------\n * This script auto-generates a unique Ticket ID, sets default status,\n * timestamps the \"Last Updated\" column, and sends an email notification\n * to IT support whenever a new form submission arrives.\n *\n * To install:\n * 1. In your Google Sheet, go to Extensions → Apps Script.\n * 2. Replace any existing code in Code.gs with this entire script.\n * 3. Save the project.\n * 4. In Apps Script, click the clock icon (Triggers) → Add Trigger.\n *    • Choose function: onFormSubmit\n *    • Deployment: Head\n *    • Event source: From spreadsheet\n *    • Event type: On form submit\n * 5. Authorize when prompted.\n */\n\n// Main function triggered on each form submission\nfunction onFormSubmit(e) {\n  // Get reference to the active spreadsheet and the \"Ticket Tracker\" sheet\n  const ss = SpreadsheetApp.getActiveSpreadsheet();\n  const sheet = ss.getSheetByName(\"Ticket Tracker\");\n  if (!sheet) {\n    // If the sheet doesn't exist, exit early\n    Logger.log(\"Sheet 'Ticket Tracker' not found. Aborting script.\");\n    return;\n  }\n\n  // Determine the last row (where the new form response landed)\n  const lastRow = sheet.getLastRow();\n  if (lastRow \u003c 2) {\n    // If for some reason there is no data row, exit early\n    Logger.log(\"No data rows found. Aborting script.\");\n    return;\n  }\n\n  // Column indices (1-based)\n  const COL_TIMESTAMP   = 1;  // Column A: Timestamp (auto-populated by Form)\n  const COL_TICKET_ID   = 2;  // Column B: Ticket ID (to be generated)\n  const COL_STATUS      = 3;  // Column C: Status (to be set to \"Open\")\n  const COL_ASSIGNED_TO = 4;  // Column D: Assigned To (left blank)\n  const COL_LAST_UPDT   = 5;  // Column E: Last Updated (timestamp)\n  const COL_NAME        = 6;  // Column F: Full Name (from Form)\n  const COL_EMAIL       = 7;  // Column G: Email Address (from Form)\n  const COL_CATEGORY    = 8;  // Column H: Issue Category (from Form)\n  const COL_PRIORITY    = 9;  // Column I: Priority (from Form)\n  const COL_DESCRIPTION = 10; // Column J: Issue Description (from Form)\n  // (Column K is File Upload if enabled)\n\n  // 1. Generate a unique Ticket ID\n  //    Format: TKT-\u003cYYYY\u003e-\u003c3-digit sequence\u003e\n  const now = new Date();\n  const yearStr = now.getFullYear().toString();\n\n  // Fetch all existing Ticket IDs in column B (from row 2 down)\n  const idRange = sheet.getRange(2, COL_TICKET_ID, lastRow - 1, 1);\n  const idValues = idRange.getValues();\n  let countThisYear = 0;\n  idValues.forEach(row =\u003e {\n    const existingId = row[0];\n    if (existingId \u0026\u0026 existingId.toString().startsWith(\"TKT-\" + yearStr)) {\n      countThisYear++;\n    }\n  });\n\n  // Next sequence number for this year, zero-padded to 3 digits\n  const seqNum = (countThisYear + 1).toString().padStart(3, \"0\");\n  const ticketId = `TKT-${yearStr}-${seqNum}`;\n\n  // Write the Ticket ID into column B of the new row\n  sheet.getRange(lastRow, COL_TICKET_ID).setValue(ticketId);\n\n  // 2. Set default Status = \"Open\"\n  sheet.getRange(lastRow, COL_STATUS).setValue(\"Open\");\n\n  // 3. Update \"Last Updated\" with the current timestamp\n  sheet.getRange(lastRow, COL_LAST_UPDT).setValue(now);\n\n  // 4. Send a notification email to IT support\n  try {\n    const requesterName  = sheet.getRange(lastRow, COL_NAME).getValue();\n    const requesterEmail = sheet.getRange(lastRow, COL_EMAIL).getValue();\n    const priority       = sheet.getRange(lastRow, COL_PRIORITY).getValue();\n    const category       = sheet.getRange(lastRow, COL_CATEGORY).getValue();\n\n    // Compose email subject and body\n    const mailSubject = `New IT Ticket: ${ticketId} (${priority})`;\n    const mailBody = `\nHello IT Team,\n\nA new IT support ticket has been submitted:\n\n• Ticket ID: ${ticketId}\n• Submitted by: ${requesterName} \u003c${requesterEmail}\u003e\n• Category: ${category}\n• Priority: ${priority}\n• Timestamp: ${formatDateTime(now)}\n\nIssue Description:\n${sheet.getRange(lastRow, COL_DESCRIPTION).getValue()}\n\nPlease review and assign this ticket as needed.\n\n-- \nThis is an automated notification from the IT Help Desk ticketing system.\n`;\n\n    // TODO: Replace with your actual IT support email (or a group alias)\n    const IT_SUPPORT_EMAIL = \"dretrevor8@gmail.com\";\n\n    MailApp.sendEmail({\n      to: IT_SUPPORT_EMAIL,\n      subject: mailSubject,\n      body: mailBody\n    });\n  } catch (err) {\n    Logger.log(\"Error sending notification email: \" + err);\n  }\n}\n\n/**\n * Helper function to format a Date object as \"YYYY-MM-DD HH:MM:SS\"\n * (You can adjust to any preferred format.)\n */\nfunction formatDateTime(date) {\n  const pad = (n) =\u003e n \u003c 10 ? \"0\" + n : n;\n  const year = date.getFullYear();\n  const month = pad(date.getMonth() + 1);\n  const day = pad(date.getDate());\n  const hours = pad(date.getHours());\n  const minutes = pad(date.getMinutes());\n  const seconds = pad(date.getSeconds());\n  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n}\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhetrox8%2Fit-helpdesk-ticketing-system","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhetrox8%2Fit-helpdesk-ticketing-system","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhetrox8%2Fit-helpdesk-ticketing-system/lists"}