diff --git a/Google_Scripts/.AE_Reminders_Daily.gs.swp b/Google_Scripts/.AE_Reminders_Daily.gs.swp deleted file mode 100644 index c26df6e9..00000000 Binary files a/Google_Scripts/.AE_Reminders_Daily.gs.swp and /dev/null differ diff --git a/Google_Scripts/AE_Reminders_Daily.gs b/Google_Scripts/AE_Reminders_Daily.gs index 1e179640..39ffda44 100644 --- a/Google_Scripts/AE_Reminders_Daily.gs +++ b/Google_Scripts/AE_Reminders_Daily.gs @@ -1,20 +1,33 @@ +/* + This script sends a daily reminder to the Sales and Marketing channel as to which + lines of data are unclean and not filled out. Currently, it is only pulling from the last 5 days. + This will be sent out between 3-4pm so that AEs can get their data in and clean before EOD. + Any questions or changes needed, see Norm. + Webhook URL in this sheet is for #sales-n-marketing channel. +*/ // Setup of the sheet const sheet = SpreadsheetApp.getActiveSheet(); // Setup of the date range to compare. Currently, it is using 5 days until Present. var now = new Date(); var formatNow = Utilities.formatDate(now, 'America/New_York', 'MM/dd/yyyy'); // Today -var daysToSubtract = 5; -var withinWeek = new Date(now.getTime()-5*(3600*24*1000)); +var daysToSubtract = 2; +var withinWeek = new Date(now.getTime()-daysToSubtract*(3600*24*1000)); var formatWeek = Utilities.formatDate(withinWeek, 'America/New_York', 'MM/dd/yyyy'); // 5 Days ago +// Counter for formatting the final list +var meetingCount = 0; + +// Other empty Globals +var finalAEList; +var tagUsers; + /* This function will create two empty arrays, one for the list of missed entries and one for tagging users in Slack First, the function gets the data ranges in spreadsheed and adds those columns to an array index. Second, the for loop cycles through the super long array (4 results per line). Based on the if statement, the loop removes all arrays that don't fit the statement. */ - function findMeetings() { // Setting up data range and empty arrays var startRow = 2; // First row of data to process var numRows = sheet.getLastRow()-1; // Number of rows to process @@ -30,19 +43,28 @@ function findMeetings() { // Setting up data range and empty arrays var date = Utilities.formatDate(row[3],'America/New_York','MM/dd/yyyy'); // Column - D var company = row[4]; // Column - E let missedEntries = [name, date, company, attended]; - // Adding a For Loop will pull a result for EACH element, aka 4 results per line. This pulls one for each group of missedEntries - // This then removes the last value (attended, since we already know it is a blank), converts to a string, and adds to a new array + /* + Adding a For Loop will pull a result for EACH element, aka 4 results per line. + This pulls one for each group of missedEntries + This then removes the last value (attended, since we already know it is a blank), converts to a string, + and adds to a new array. The counter will compare if there is more than one entry in the array. + */ if ((missedEntries[3] == "") && (missedEntries[1] >= formatWeek) && (missedEntries[1] <= formatNow)) { + meetingCount += 1; missedEntries.pop(); missedEntries.toString(); slackingAEListOne.push(missedEntries); + //Logger.log(slackingAEListOne); }; }; - // Now outside of the if statement: - // the array is built, and we want each group to be on a new line, remove the commas and add a hyphen. - var slackingAEListTwo = slackingAEListOne.splice(1).join('\n'); - var finalAEList = slackingAEListTwo.replace(/,/g, ' - ') - + /* Now outside of the if statement: + the array is built, and we want each group to be on a new line, remove the commas and add a hyphen. + The counter counts if there is 1 or more meetings, or not. If 0, it sends a certain message, not tagging anyone. + If it is one or more, it splices by the first array (index 0), adds a new line, and replaces commans with hyphens. + */ + if (meetingCount >= 1) { + var slackingAEListTwo = slackingAEListOne.splice(0).join('\n'); + var finalAEList = slackingAEListTwo.replace(/,/g, ' - '); // This if statement is going to only tag those who appear in the previous list. // No need to tag people who have done their work and contribute to clean data. if (finalAEList.includes('Norm')) { @@ -57,79 +79,133 @@ function findMeetings() { // Setting up data range and empty arrays if (finalAEList.includes('Charles')) { tagList.push('<@U01286MQUS2>'); } - var tagUsers = tagList.toString(); - - /* Now, we're building the payload for the Slack Message. + if (finalAEList.includes('Travis')) { + tagList.push('<@UFE3T14UX>'); + } + if (finalAEList.includes('Nick')) { + tagList.push('<@U0276LMA70F>'); + } + if (finalAEList.includes('Mike')) { + tagList.push('<@U027MAQUPM0>'); + } + var tagUsers = tagList.toString(); + /* + Now, we're building the payload for the Slack Message. This is very specific and prone to errors, so check that it works using Slack's tool: - https://app.slack.com/block-kit-builder/ */ - - let payloadText = + https://app.slack.com/block-kit-builder/ + + Copy from Rich: + ":rotating_light::rotating_light::rotating_light: New Meeting Tracker Alert! :rotating_light::rotating_light::rotating_light: + It's your daily reminder to update the new meeting tracker. + If you've been tagged, please address this by EOD." + */ + let payloadText = { - "blocks": [ + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":rotating_light::rotating_light::rotating_light: New Meeting Tracker Alert! :rotating_light::rotating_light::rotating_light:" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "It's your daily reminder to update the new meeting tracker." + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "If you've been tagged, please address this by EOD." + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": finalAEList // Sends list with AE, meeting date, and company + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "In case you need it, here's a link to the sheet. :point_right:" + }, + "accessory": { + "type": "button", + "text": { + "type": "plain_text", + "text": "Sales New Meeting Tracker", + "emoji": true + }, + "value": "sales_tracker_link_123", + "url": "https://docs.google.com/spreadsheets/d/150nSuHQLJHpJaYdQ6KHeN7nQ6iexwtnQEpicM77PK8A/edit#gid=0 | First Meeting Tracker", + "action_id": "button-action" + } + }, + { + "type": "divider" + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": tagUsers // Tags with slack user numbers if they appear in finalSend + } + } + ] +}; + // This is standard operating procedure to creating the payload and destination + const webhook = "https://hooks.slack.com/services/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"; + const options = { + method: "post", + contentType: "application/json", + muteHttpExceptions: true, + payload: JSON.stringify(payloadText), + }; + const sendMsg = UrlFetchApp.fetch(webhook, options); + var respCode = sendMsg.getResponseCode(); + //Logger.log(sendMsg); // Debug to confirm send + //Logger.log(respCode); // Debug to show errors, if any + /* + This is the else statement that sends a certain message not tagging anyone and saying that data is clean. + */ + } else { + let noMeetingMsg = + { + "blocks": [ { "type": "section", "text": { "type": "mrkdwn", - "text": ":bell: *Have you filled out the Sales New Meeting Tracker?* :bell:" - } - }, - { - "type": "divider" - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "If you're tagged, you haven't filled it out." + "text": ":star::star::star: New Meeting Tracker Alert! :star::star::star:" } }, { "type": "section", "text": { "type": "mrkdwn", - "text": finalAEList // Sends list with AE, meeting date, and company - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Here, a convenient link to the sheet!:point_right: :point_right: :point_right: :point_right:" - }, - "accessory": { - "type": "button", - "text": { - "type": "plain_text", - "text": "Sales New Meeting Tracker", - "emoji": true - }, - "value": "sales_tracker_link_123", - "url": "https://docs.google.com/spreadsheets/d/1o01hj9oOoAR4TeJxXDuA3R7bHNbyCB3eaGJunK6-ojg/edit#gid=0 | First Meeting Tracker", - "action_id": "button-action" - } - }, - { - "type": "divider" - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": tagUsers // Tags with slack user numbers if they appear in finalSend + "text": "Good job, everyone! All meetings from the last 5 days are up to date. Keep doing what you're doing!" } } ] }; - // This is standard operating procedure to creating the payload and destination - const webhook = "https://hooks.slack.com/services/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"; - const options = { - method: "post", - contentType: "application/json", - muteHttpExceptions: true, - payload: JSON.stringify(payloadText), - }; - const sendMsg = UrlFetchApp.fetch(webhook, options); - var respCode = sendMsg.getResponseCode(); - Logger.log(sendMsg); // Debug to confirm send - Logger.log(respCode); // Debug to show errors, if any -}; +// This is standard operating procedure to creating the payload and destination + const webhook = "https://hooks.slack.com/services/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"; + const options = { + method: "post", + contentType: "application/json", + muteHttpExceptions: true, + payload: JSON.stringify(noMeetingMsg), + }; + const sendMsg = UrlFetchApp.fetch(webhook, options); + var respCode = sendMsg.getResponseCode(); + //Logger.log(sendMsg); // Debug to confirm send + //Logger.log(respCode); // Debug to show errors, if any +} +}; \ No newline at end of file diff --git a/Google_Scripts/Sheets>Jira.gs b/Google_Scripts/Sheets>Jira.gs index 798bf43c..e4c5e0c4 100644 --- a/Google_Scripts/Sheets>Jira.gs +++ b/Google_Scripts/Sheets>Jira.gs @@ -1,86 +1,131 @@ +/* Pertinent Information and Codes: +Custom Fields: +Channel = customfield_10121 +Campaign = customfield_10120 +SDR = customfield_10122 +Start Date = customfield_10015 + +Users: +Travis Nardin = 5d9cb42c0265ca0db955b965 +Dan Peski = 603318815ddf020069969cad +Norm Rasmussen = 6092af20d353800068863d15 +Michael Valido = 61fbf60cd8d7cf006a90941c +Jon Newfield = 6092af212c2f6c0068ec92c4 +Isabel Katz = 620145241fec260068c107e5 +Charles McGovern = 5eaaf1c4021ae30ba8fcb184 +Nick Zuppe = 60eddda64257a90070aeebef +Doug Goldsmith = 61294a4845f753006951a590 +Nick Appleby = 6183eab7892c420072f9c437 +Quba Williams-Wilfong = 62101fe4e41f76006a6f6510 + +Without accounts: Adan, Drew + +*/ +var count = 0; +var list; +var finalEntry; + function myFunction() { - var URL = "https://northpass.atlassian.net/rest/api/2/issue"; - var accountID = "6092af20d353800068863d15"; - var token = "2NrKYv22TLWnxTo7EhU3633E"; - var UserCredentials = "Basic " + Utilities.base64Encode(accountID+":"+token); + var URL = "https://northpass.atlassian.net/rest/api/3/issue/"; + // var accountID = "6092af20d353800068863d15"; + var token = "2NrKYv22TLWnxTo7EhU3633E"; + // var UserCredentials = Utilities.base64Encode(accountID + ":" + token); + var user = "nrasmussen@northpass.com"; + // var pass = "c9QK\>4^fxiHt!"; + var UserCredentials = Utilities.base64Encode(user + ":" + token); - // Setting up data range and empty arrays - const sheet = SpreadsheetApp.getActiveSheet(); + // Setting up data range and empty arrays + const sheet = SpreadsheetApp.getActiveSheet(); + var startRow = 244; // First col of data to process + var numRows = 450; // Number of rows to process + var dataRange = sheet.getRange(startRow, 1, numRows, sheet.getLastColumn()).getValues(); + var data = dataRange.filter(function(r){ + return r.join("").length>0; + }); + var sdr = ""; - for (i in data) { // For a data row within the entire data range - var startRow = 2; // First row of data to process - var numRows = sheet.getLastRow()-1; // Number of rows to process - var dataRange = sheet.getRange(startRow, 1, numRows, sheet.getLastColumn()); - var data = dataRange.getValues(); - let row = data[i]; - let name = row[1]; // Column - B - var meetingDate = Utilities.formatDate(row[3],'America/New_York','MM/dd/yyyy'); // Column - D - var company = row[4]; // Column - E - let list = [name, company, meetingDate]; - - if (list[0] == "Norm") { - Logger.log(list) - var data = { - "fields": { - "project" : { - "key" : "2NrKYv22TLWnxTo7EhU3633E" - }, - "summary" : list[1], - "description" : "Meeting scheduled for " + list[3], - "date" : list[3], - "issuetype": { - "name" : Task - } + for (i in data) { // For a data col within the entire data range + var col = data[i]; + let sdr = col[0]; // Column - A + let name = col[1]; // Column - B + let rawDate = Utilities.formatDate(col[3], 'America/New_York', 'yyyy-MM-dd'); + let bookingDate = Utilities.formatDate(col[2], 'America/New_York', 'MM/dd/yyyy'); // Column - C + let meetingDate = Utilities.formatDate(col[3], 'America/New_York', 'MM/dd/yyyy'); // Column - D + let company = col[4]; // Column - E + let channel = col[5]; // Column - F + let result = col[7]; // Column - H + let campaign = col[8]; // Column - I + let info = col[9]; // Column - J + let list = [sdr, name, rawDate ,bookingDate, meetingDate, company, channel, result, campaign, info]; + list.toString(); + let sdrDict = { + "Mike" : + "61fbf60cd8d7cf006a90941c", + "Nick" : + "60eddda64257a90070aeebef", + "Appleby" : + "6183eab7892c420072f9c437", + "Doug" : + "61294a4845f753006951a590", + "Quba" : + "62101fe4e41f76006a6f6510", + }; + if (list.includes("Norm")) { + var data = { + "fields": { + "project": { + "key": "NORMPIPE", + }, + "issuetype": { + "id": "10268", + }, + "summary": list[5], + "description": { + "type": "doc", + "version": 1, + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": "Booked Date - " + list[3] + '\n' + + "Meeting Date - " + list[4] + '\n' + + "Description from Tracker: " + list[9] + '\n' + + "Last Status - " + list[7] } - }; - }; - }; - - var payload = JSON.stringify(data); - - var headers = { "Accept":"application/json", - "Content-Type":"application/json", - "Authorization":UserCredentials, - "muteHttpExceptions":"True" - } - var options = { "method":"POST", - "headers": headers, - "payload": payload - }; - - var response = UrlFetchApp.fetch(URL, options); - Logger.log(response); - -}; - -// LONG JSON -var data = { - "fields": { - "issuetype": { - "id" : "10203" - }, - "parent": { - "key": "NORMPIPE", - "id": "10203", - }, - "project" : { - "id" : "10052", - "key" : "NORMPIPE", - }, - "description" : "Meeting scheduled for " + list[3],{ - "type" : "doc", - "version" : 1, - "content": [ - { - "type": "paragraph", - "content": [ - { - "text" : "Meeting scheduled for " + list[3], - "type" : "text", - } - ] - }, - ] - }, + ] + } + ], + }, + "customfield_10015": list[2], // Start (Meeting) Date - rawDate + "customfield_10120": [ // Campaign + list[8] + ], + "customfield_10122": [{"id" : sdrDict[list[0]]}], // SDR + "customfield_10121": [ // Channel + list[6] + ], + } }, - }; \ No newline at end of file + payload = JSON.stringify(data); + Logger.log(payload); + var headers = { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Basic " + UserCredentials, + "muteHttpExceptions": true, + } + var options = { + "method": "POST", + "headers": headers, + "payload": payload + } + //Logger.log(options); + var response = UrlFetchApp.fetch(URL, options); + //Logger.log(response); + var respCode = response.getResponseCode(); + //Logger.log(respCode); + } + } +}; \ No newline at end of file