From 064098be7057fba2495716e4d270c28b933a4c19 Mon Sep 17 00:00:00 2001 From: psteiwer Date: Fri, 24 Jan 2020 12:51:22 -0500 Subject: [PATCH 01/37] Add ActionCommand method This method generates a command for use in custom actions --- PivotSubscriptions/Utility.cls | 389 +++++++++++++++++---------------- 1 file changed, 200 insertions(+), 189 deletions(-) diff --git a/PivotSubscriptions/Utility.cls b/PivotSubscriptions/Utility.cls index 84a6e94..e75231b 100644 --- a/PivotSubscriptions/Utility.cls +++ b/PivotSubscriptions/Utility.cls @@ -1,189 +1,200 @@ -Class PivotSubscriptions.Utility -{ - -ClassMethod GetVersion() As %String -{ - Quit "v1.0.1" -} - -/// Utility method for saving and updating global variables -ClassMethod ConfigureSettings(pAdminEmail, pHttp, pServer, pPort) { - Set ^PivotSubscriptions.Settings("AdminEmail")=pAdminEmail - Set ^PivotSubscriptions.Settings("Http")=pHttp - Set ^PivotSubscriptions.Settings("Server")=pServer - Set ^PivotSubscriptions.Settings("Port")=pPort - - Quit $$$OK -} - -ClassMethod CheckConfigurationGlobal(pConfigurationOptionName As %String) -{ - If ((pConfigurationOptionName'="") && $DATA(^PivotSubscriptions.Settings(pConfigurationOptionName))) { - If (^PivotSubscriptions.Settings(pConfigurationOptionName)'="") { - Quit 1 - } - } - - Quit 0 -} - -ClassMethod GenerateLink(ByRef link As %String) As %Status -{ - Set tSC=$$$OK - - Set tSC=##class(%Library.RoutineMgr).GetWebServerPort(.p,.h,.up,.url) - If $$$ISERR(tSC) Quit tSC - - If ..CheckConfigurationGlobal("Http") { - Set tWebServerPortUrl=^PivotSubscriptions.Settings("Http") - } Else { - Set tWebServerPortUrl="http://" - } - - If ..CheckConfigurationGlobal("Server") { - Set tWebServerPortUrl=tWebServerPortUrl_^PivotSubscriptions.Settings("Server") - } Else { - Set tWebServerPortUrl=tWebServerPortUrl_h - } - - If ..CheckConfigurationGlobal("Port") { - Set tWebServerPortUrl=tWebServerPortUrl_":"_^PivotSubscriptions.Settings("Port") - } Else { - If '..CheckConfigurationGlobal("Server") { - Set tWebServerPortUrl=tWebServerPortUrl_":"_p - } - } - - Set tNamespace=$System.CSP.GetDefaultApp($Namespace) - Set tApplicationName="/PivotSubscriptions.UI.SubscriptionManager.zen" - - Set link=tWebServerPortUrl_tNamespace_tApplicationName - - Quit tSC -} - -ClassMethod CheckTable(pName As %String) As %Status -{ - Set tFilename=$replace($zstrip(pName,"*PC'W",,"/")_" - "_$zd($h,6),"/","-")_".xls" - - // embed pivot table as HTML table to email - Set tStream=##class(%Stream.FileCharacter).%New() - Set tSC=tStream.LinkToFile(tFilename) - - // check that file is valid file - If $$$ISERR(tSC) Quit tSC - - Set tTableStatus=0 - Set headerCount=0 - // iterate through stream to check that table has actual data - While 'tStream.AtEnd { - Set line = tStream.ReadLine() - - If $Find(line, " 20) { - Set tTableStatus=0 - } - Quit - } - } - - Quit tTableStatus -} - -/// Write header for any email, including styling -ClassMethod WriteEmailHeader(pMsg As %Net.MailMessage) -{ - Do pMsg.TextData.WriteLine("") - Do pMsg.TextData.WriteLine("") - Do pMsg.TextData.WriteLine("") - Do pMsg.TextData.WriteLine("
 

") -} - -/// Write footer for any email, including link generation -ClassMethod WriteEmailFooter(pMsg As %Net.MailMessage) -{ - Do ##class(PivotSubscriptions.Utility).GenerateLink(.link) - - Do pMsg.TextData.WriteLine("

") - Do pMsg.TextData.WriteLine("
 
 
You can manage your subscriptions here.
You can edit days of the week/time/format/recipients and delete in the Subscriptions Manager portal.
 
") - Do pMsg.TextData.WriteLine("") - Do pMsg.TextData.WriteLine("
 

Pivot Subscriptions by DeepSee

2019 InterSystems Corporation

One Memorial Drive, Cambridge, MA 02142

 
") -} - -/// Write improved email format for subscription, including embeded pivot table -ClassMethod WriteEmail(pName As %String, pMsg As %Net.MailMessage, pTableStatus) -{ - Do ##class(PivotSubscriptions.Utility).WriteEmailHeader(pMsg) - - Set tFilename=$replace($zstrip(pName,"*PC'W",,"/")_" - "_$zd($h,6),"/","-")_".xls" - - // embed pivot table as HTML table to email - Set tStream=##class(%Stream.FileCharacter).%New() - Set tSC=tStream.LinkToFile(tFilename) - If $$$ISERR(tSC) Quit tSC - - // check subscription to see if its table has error status - If pTableStatus { - // .xls to String stream that is read by line and then written to the email (as HTML) by line - While 'tStream.AtEnd { - Set line=tStream.ReadLine() - - // properly center and format table to match the rest of the style of the email - If line="" { - Do pMsg.TextData.WriteLine("
") - } ElseIf line="
" { - Do pMsg.TextData.WriteLine("
")) || ($Find(line, "")) || (line = "")) { - Continue - } Else { - Do pMsg.TextData.WriteLine(line) - } - } - } Else { - // custom error message - Do pMsg.TextData.WriteLine("Pivot table is unpopulated or too big. Please see Excel table.") - } - - Do ##class(PivotSubscriptions.Utility).WriteEmailFooter(pMsg) -} - -ClassMethod SendErrorMessage(pPivot As %String, pEmail As %String, pName As %String) As %Status -{ - Set tLog=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, $ZDATE($HOROLOG,10), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2), "", pEmail, pName) - - If $$$ISERR(tLog) Quit tLog - - // Generate email - Set server=##class(%Net.SMTP).%New() - Set server.smtpserver = ##class(%SYS.Task.Config).GetData("MailServer") - Set msg=##class(%Net.MailMessage).%New() - Set msg.From="PivotSubscriptions" - Set msg.ReplyTo=^PivotSubscriptions.Settings("AdminEmail") // replace with admin email - - // Remove ".pivot" extension for subject - Set msg.Subject="Table Error detected for "_pName - Set msg.IsBinary=0 - Set msg.IsHTML=1 // Set IsHTML to 1 if email uses HTML - - Do ##class(PivotSubscriptions.Utility).WriteEmailHeader(msg) - Do msg.TextData.WriteLine("There was an table error detected for "_pName_" based on "_$E(pPivot,1,*-6)_", either there being no data populated in the table or the pivot table being too large to be embedded or truncated in the PDF.

Please check the Subscription Manager.") - Do ##class(PivotSubscriptions.Utility).WriteEmailFooter(msg) - - // Set recipient of email - Do msg.To.SetAt(pEmail,1) - - // Send email - Set tSC=server.Send(msg) - - Quit tSC -} - -} +Class PivotSubscriptions.Utility +{ + +ClassMethod GetVersion() As %String +{ + Quit "v1.0.1" +} + +/// Utility method for saving and updating global variables +ClassMethod ConfigureSettings(pAdminEmail, pHttp, pServer, pPort) +{ + Set ^PivotSubscriptions.Settings("AdminEmail")=pAdminEmail + Set ^PivotSubscriptions.Settings("Http")=pHttp + Set ^PivotSubscriptions.Settings("Server")=pServer + Set ^PivotSubscriptions.Settings("Port")=pPort + + Quit $$$OK +} + +ClassMethod CheckConfigurationGlobal(pConfigurationOptionName As %String) +{ + If ((pConfigurationOptionName'="") && $DATA(^PivotSubscriptions.Settings(pConfigurationOptionName))) { + If (^PivotSubscriptions.Settings(pConfigurationOptionName)'="") { + Quit 1 + } + } + + Quit 0 +} + +ClassMethod GenerateLink(ByRef link As %String) As %Status +{ + Set tSC=$$$OK + + Set tSC=##class(%Library.RoutineMgr).GetWebServerPort(.p,.h,.up,.url) + If $$$ISERR(tSC) Quit tSC + + If ..CheckConfigurationGlobal("Http") { + Set tWebServerPortUrl=^PivotSubscriptions.Settings("Http") + } Else { + Set tWebServerPortUrl="http://" + } + + If ..CheckConfigurationGlobal("Server") { + Set tWebServerPortUrl=tWebServerPortUrl_^PivotSubscriptions.Settings("Server") + } Else { + Set tWebServerPortUrl=tWebServerPortUrl_h + } + + If ..CheckConfigurationGlobal("Port") { + Set tWebServerPortUrl=tWebServerPortUrl_":"_^PivotSubscriptions.Settings("Port") + } Else { + If '..CheckConfigurationGlobal("Server") { + Set tWebServerPortUrl=tWebServerPortUrl_":"_p + } + } + + Set tNamespace=$System.CSP.GetDefaultApp($Namespace) + Set tApplicationName="/PivotSubscriptions.UI.SubscriptionManager.zen" + + Set link=tWebServerPortUrl_tNamespace_tApplicationName + + Quit tSC +} + +ClassMethod CheckTable(pName As %String) As %Status +{ + Set tFilename=$replace($zstrip(pName,"*PC'W",,"/")_" - "_$zd($h,6),"/","-")_".xls" + + // embed pivot table as HTML table to email + Set tStream=##class(%Stream.FileCharacter).%New() + Set tSC=tStream.LinkToFile(tFilename) + + // check that file is valid file + If $$$ISERR(tSC) Quit tSC + + Set tTableStatus=0 + Set headerCount=0 + // iterate through stream to check that table has actual data + While 'tStream.AtEnd { + Set line = tStream.ReadLine() + + If $Find(line, " 20) { + Set tTableStatus=0 + } + Quit + } + } + + Quit tTableStatus +} + +/// Write header for any email, including styling +ClassMethod WriteEmailHeader(pMsg As %Net.MailMessage) +{ + Do pMsg.TextData.WriteLine("") + Do pMsg.TextData.WriteLine("
") + Do pMsg.TextData.WriteLine("") + Do pMsg.TextData.WriteLine("
 

") +} + +/// Write footer for any email, including link generation +ClassMethod WriteEmailFooter(pMsg As %Net.MailMessage) +{ + Do ##class(PivotSubscriptions.Utility).GenerateLink(.link) + + Do pMsg.TextData.WriteLine("

") + Do pMsg.TextData.WriteLine("
 
 
You can manage your subscriptions here.
You can edit days of the week/time/format/recipients and delete in the Subscriptions Manager portal.
 
") + Do pMsg.TextData.WriteLine("") + Do pMsg.TextData.WriteLine("
 

Pivot Subscriptions by DeepSee

2019 InterSystems Corporation

One Memorial Drive, Cambridge, MA 02142

 
") +} + +/// Write improved email format for subscription, including embeded pivot table +ClassMethod WriteEmail(pName As %String, pMsg As %Net.MailMessage, pTableStatus) +{ + Do ##class(PivotSubscriptions.Utility).WriteEmailHeader(pMsg) + + Set tFilename=$replace($zstrip(pName,"*PC'W",,"/")_" - "_$zd($h,6),"/","-")_".xls" + + // embed pivot table as HTML table to email + Set tStream=##class(%Stream.FileCharacter).%New() + Set tSC=tStream.LinkToFile(tFilename) + If $$$ISERR(tSC) Quit tSC + + // check subscription to see if its table has error status + If pTableStatus { + // .xls to String stream that is read by line and then written to the email (as HTML) by line + While 'tStream.AtEnd { + Set line=tStream.ReadLine() + + // properly center and format table to match the rest of the style of the email + If line="" { + Do pMsg.TextData.WriteLine("
") + } ElseIf line="
" { + Do pMsg.TextData.WriteLine("
")) || ($Find(line, "")) || (line = "")) { + Continue + } Else { + Do pMsg.TextData.WriteLine(line) + } + } + } Else { + // custom error message + Do pMsg.TextData.WriteLine("Pivot table is unpopulated or too big. Please see Excel table.") + } + + Do ##class(PivotSubscriptions.Utility).WriteEmailFooter(pMsg) +} + +ClassMethod SendErrorMessage(pPivot As %String, pEmail As %String, pName As %String) As %Status +{ + Set tLog=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, $ZDATE($HOROLOG,10), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2), "", pEmail, pName) + + If $$$ISERR(tLog) Quit tLog + + // Generate email + Set server=##class(%Net.SMTP).%New() + Set server.smtpserver = ##class(%SYS.Task.Config).GetData("MailServer") + Set msg=##class(%Net.MailMessage).%New() + Set msg.From="PivotSubscriptions" + Set msg.ReplyTo=^PivotSubscriptions.Settings("AdminEmail") // replace with admin email + + // Remove ".pivot" extension for subject + Set msg.Subject="Table Error detected for "_pName + Set msg.IsBinary=0 + Set msg.IsHTML=1 // Set IsHTML to 1 if email uses HTML + + Do ##class(PivotSubscriptions.Utility).WriteEmailHeader(msg) + Do msg.TextData.WriteLine("There was an table error detected for "_pName_" based on "_$E(pPivot,1,*-6)_", either there being no data populated in the table or the pivot table being too large to be embedded or truncated in the PDF.

Please check the Subscription Manager.") + Do ##class(PivotSubscriptions.Utility).WriteEmailFooter(msg) + + // Set recipient of email + Do msg.To.SetAt(pEmail,1) + + // Send email + Set tSC=server.Send(msg) + + Quit tSC +} + +ClassMethod ActionCommand(ByRef pContext As %ZEN.proxyObject) As %String +{ + Set tCommand="" + If pContext.dataSource'="" { + Set tCommand="popup:PivotSubscriptions.UI.Dialog.EditSubscription.cls?SUBSCRIPTIONID=0&PIVOTNAME="_$zconvert(pContext.dataSource,"O","URL") + } + + Quit tCommand +} + +} From c29e763b315007f2299de50845208e24aabef406 Mon Sep 17 00:00:00 2001 From: psteiwer Date: Fri, 24 Jan 2020 13:10:28 -0500 Subject: [PATCH 02/37] Update README with Custom Action instructions --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 18550f5..3c33c33 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,17 @@ To ensure that links to the SubscriptionManager page are correctly generated, th ### Configure Task Manager Email Settings Subscriptions are delivered by Email. The Task Manager Email must be configured to allow alerts to be delivered by Email. At a minimum, the SMTP Server must be assigned in the Task Manager Email Settings (Management Portal -> System Administration -> Configuration -> Additional Settings -> Task Manager Email). For more information, please see the documentation. + +### Optional: Custom Action +The Piovt List page gives access to a list of Pivot Tables available to the user. From there, a Pivot Subscription can be added. However, if you would like to add a Pivot Subscription directly from Analyzer or from a Dashboard, you will need to configure a new Custom Action. In order to add the Custom Action, an Action Class is first needed. For more information, please see the documentation for defining custom actions. In your Action KPI, define the new action as: +``` + +``` +Additionally in your Action KPI, define the new condition in %OnDashboardAction as: +``` +If (pAction="AddPivotSubscription") { + Set pContext.command = ##class(PivotSubscriptions.Utility).ActionCommand(.pContext) +} +``` + +The ActionCommand Method will generate a command that will allow for the creation of the Pivot Subscription \ No newline at end of file From 7581d488c638a38f0f51fdc539001879efda2f49 Mon Sep 17 00:00:00 2001 From: psteiwer Date: Fri, 14 Feb 2020 12:09:47 +0100 Subject: [PATCH 03/37] Update EventLog EventLog now will log Start and End times for send event Previously, only the Start time was logged. In addition to adding the End time, the status of the SendEmail method is also logged --- PivotSubscriptions/EventLog.cls | 223 +++++++++-------- PivotSubscriptions/Task.cls | 408 ++++++++++++++++---------------- PivotSubscriptions/Utility.cls | 3 +- 3 files changed, 331 insertions(+), 303 deletions(-) diff --git a/PivotSubscriptions/EventLog.cls b/PivotSubscriptions/EventLog.cls index a8b694b..6f281f9 100644 --- a/PivotSubscriptions/EventLog.cls +++ b/PivotSubscriptions/EventLog.cls @@ -1,101 +1,122 @@ -/// Event Log is a log for every action performed by Pivot Subscriptions, covering five event types: creation, update, deletion, sent email subscriptions by Task, and immediately sent emails. -Class PivotSubscriptions.EventLog Extends %Persistent -{ - -/// Event Type covers: creation, update, deletion and sent email subscriptions -/* - * Only possible values are creation, update, deletion, send, and tableError - */ -Property EventType As %String (VALUELIST=",creation,update,deletion,send,tableError"); - -Property TimeStamp As %TimeStamp [ InitialExpression = {$zdt($h, 3, 1)} ]; - -Property UserName As %String(MAXLEN = 128) [ InitialExpression = {$username} ]; - -Property Pivot As %String(MAXLEN = 512); - -Property DayOfWeek As %String; - -Property Hour As %Integer(MINVAL=0, MAXVAL=23); - -Property Minute As %Integer (MINVAL=0, MAXVAL=59); - -Property Format As %String(VALUELIST = ",Excel,PDF"); - -Property Emails As %String; - -Property Name As %String; - -/// Takes in info about an Alert Task and logs the information to the TaskLog -ClassMethod LogEvent(pEvent, pUser, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName) As %Status -{ - Set tSC=$$$OK - - Set tEventLog=##class(PivotSubscriptions.EventLog).%New() - Set tEventLog.EventType=pEvent - Set tEventLog.TimeStamp=$zdt($h, 3, 1) - Set tEventLog.UserName=pUser - Set tEventLog.Pivot=pPivot - Set tEventLog.Name=pName - - Set tEventLog.DayOfWeek=pDayOfWeek - Set tEventLog.Hour=pHour - Set tEventLog.Minute=pMinute - - Set tEventLog.Format=pFormat - Set tEventLog.Emails=pEmails - - Set tSC=tEventLog.%Save() - - Quit tSC -} - -Storage Default -{ - - -%%CLASSNAME - - -EventType - - -TimeStamp - - -UserName - - -Pivot - - -SubscriptionId - - -DayOfWeek - - -Hour - - -Minute - - -Format - - -Emails - - -Name - - -^PivotSubscriptions.EventLogD -EventLogDefaultData -^PivotSubscriptions.EventLogD -^PivotSubscriptions.EventLogI -^PivotSubscriptions.EventLogS -%Storage.Persistent -} - -} \ No newline at end of file +/// Event Log is a log for every action performed by Pivot Subscriptions, covering five event types: creation, update, deletion, sent email subscriptions by Task, and immediately sent emails. +Class PivotSubscriptions.EventLog Extends %Persistent +{ + +/* + * Only possible values are creation, update, deletion, send, and tableError + */ +/// Event Type covers: creation, update, deletion and sent email subscriptions +Property EventType As %String(VALUELIST = ",creation,update,deletion,send,tableError"); + +Property StartTime As %TimeStamp [ InitialExpression = {$zdt($h, 3, 1)} ]; + +Property EndTime As %TimeStamp; + +Property UserName As %String(MAXLEN = 128) [ InitialExpression = {$username} ]; + +Property Pivot As %String(MAXLEN = 512); + +Property DayOfWeek As %String; + +Property Hour As %Integer(MAXVAL = 23, MINVAL = 0); + +Property Minute As %Integer(MAXVAL = 59, MINVAL = 0); + +Property Format As %String(VALUELIST = ",Excel,PDF"); + +Property Emails As %String; + +Property Name As %String; + +Property Status As %Status; + +/// Takes in info about an Alert Task and logs the information to the TaskLog +ClassMethod LogEvent(pType, pUser, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName, ByRef pEvent) As %Status +{ + Set tSC=$$$OK + + Set tEventLog=##class(PivotSubscriptions.EventLog).%New() + Set tEventLog.EventType=pType + Set tEventLog.UserName=pUser + Set tEventLog.Pivot=pPivot + Set tEventLog.Name=pName + + Set tEventLog.DayOfWeek=pDayOfWeek + Set tEventLog.Hour=pHour + Set tEventLog.Minute=pMinute + + Set tEventLog.Format=pFormat + Set tEventLog.Emails=pEmails + + Set tSC=tEventLog.%Save() + Set pEvent=tEventLog + + Quit tSC +} + +Method LogUpdate(pStatus) As %Status +{ + Set tSC=$$$OK + + Set ..EndTime=$zdt($h,3,1) + Set ..Status=pStatus + Set tSC=..%Save() + + Quit tSC +} + +Storage Default +{ + + +%%CLASSNAME + + +EventType + + +StartTime + + +UserName + + +Pivot + + +SubscriptionId + + +DayOfWeek + + +Hour + + +Minute + + +Format + + +Emails + + +Name + + +EndTime + + +Status + + +^PivotSubscriptions.EventLogD +EventLogDefaultData +^PivotSubscriptions.EventLogD +^PivotSubscriptions.EventLogI +^PivotSubscriptions.EventLogS +%Storage.Persistent +} + +} diff --git a/PivotSubscriptions/Task.cls b/PivotSubscriptions/Task.cls index ebcb7a9..e8e3b09 100644 --- a/PivotSubscriptions/Task.cls +++ b/PivotSubscriptions/Task.cls @@ -1,202 +1,208 @@ -Class PivotSubscriptions.Task Extends %SYS.Task.Definition -{ - -Parameter TaskName = "Pivot Subscriptions Task"; - -Method OnTask() As %Status -{ - Set tSC=$$$OK - - // Construct current day and time for query - Set tDayOfWeek=$ZDATE($HOROLOG,10) - Set tHour=$PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1) - Set tMinute=$PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2) - - If $G(^PivotSubscriptions.Settings("TestEnv")) { - // Ignore minute for testing purposes - // This will allow the task to be run on demand and send emails immediately - // Leaving DayOfWeek and Hour so the scheduled task does not spam emails - Set tRS=##class(%SQL.Statement).%ExecDirect(,"SELECT Emails,Name,Pivot,Format,DayOfWeek,""Hour"",""Minute"" FROM PivotSubscriptions.Subscription WHERE DayOfWeek[? AND ""Hour""=?",tDayOfWeek,tHour) - } Else { - Set tRS=##class(%SQL.Statement).%ExecDirect(,"SELECT Emails,Name,Pivot,Format,DayOfWeek,""Hour"",""Minute"" FROM PivotSubscriptions.Subscription WHERE DayOfWeek[? AND ""Hour""=? AND ""Minute""=?",tDayOfWeek,tHour,tMinute) - } - - // Loop through Subscription results and send emails. - While tRS.%Next() { - Set tEmails=tRS.%Get("Emails") - Set tPivot=tRS.%Get("Pivot") - Set tFormat=tRS.%Get("Format") - Set tDayOfWeek=tRS.%Get("DayOfWeek") - Set tHour=tRS.%Get("Hour") - Set tMinute=tRS.%Get("Minute") - Set tName=tRS.%Get("Name") - - Set tSC = ##class(PivotSubscriptions.Task).SendSubscription(tPivot,tEmails,tFormat,tDayOfWeek,tHour,tMinute,tName) - } - - Quit tSC -} - -ClassMethod SendSubscription(pPivot As %String, pEmails As %String, pFormat As %String,pDayOfWeek,pHour,pMinute,pName) As %Status -{ - Set tSC=$$$OK - - Set tSC=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName) - If $$$ISERR(tSC) Quit tSC - - If pName="" { - Set pName=$E(pPivot,1,*-6) - } - - Set tSC=##class(PivotSubscriptions.Task).SendEmail(pPivot,pEmails,pFormat,pName) - If $$$ISERR(tSC) Quit tSC - - If '(##class(PivotSubscriptions.Utility).CheckTable(pName)) { - Set tSC=##class(PivotSubscriptions.EventLog).LogEvent("tableError", $username, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName) - If $$$ISERR(tSC) Quit tSC - } - - Quit tSC -} +Class PivotSubscriptions.Task Extends %SYS.Task.Definition +{ -ClassMethod SendEmail(pPivot As %String, pEmails As %String, pFormat As %String, pName As %String) As %Status -{ - Set tSC=$$$OK - Set tFilename="" - - Set mdx=##class(%DeepSee.Utils).%GetMDXFromPivot(pPivot,.tSC,0) - - // Execute MDX to see if there are results - Set tHasResults=0 - Set tRS=##class(%DeepSee.ResultSet).%New() - Do tRS.%PrepareMDX(mdx) - Do tRS.%Execute() - If tRS.%Query.queryType="DRILLTHROUGH" { - If tRS.listingRows>0 { - Set tHasResults=1 - } - } Else { - If tRS.%GetGrandTotal()'=0 { - Set tHasResults=1 - } - } - - // Only generate file if requested pivot has results - If tHasResults { - Set pParms("TITLE")=pName - Set pParms("SUBTITLE")=$E(pPivot,1,*-6)_". Report generated on "_$zd($h,6) - Set pParms("MDX")=mdx - - Set tFilename=$replace($zstrip(pName,"*PC'W",,"/")_" - "_$zd($h,6),"/","-")_".xls" - Set tSC=##class(%DeepSee.Utils).%ExportExcelToFile(tFilename,.pParms) - } - If $$$ISERR(tSC) Quit tSC - - // Generate email - If tSC { - // check whether the table generated is too wide/truncated AND whether the table has data - Set tableStatus=##class(PivotSubscriptions.Utility).CheckTable(pName) - - Set server=##class(%Net.SMTP).%New() - Set server.smtpserver=##class(%SYS.Task.Config).GetData("MailServer") - Set msg=##class(%Net.MailMessage).%New() - Set msg.From="PivotSubscriptions" - - Set validAdminEmail=##class(PivotSubscriptions.Utility).CheckConfigurationGlobal("AdminEmail") - - If validAdminEmail { - Set msg.ReplyTo=^PivotSubscriptions.Settings("AdminEmail") - } - - // Remove ".pivot" extension for subject - Set msg.Subject=pName - Set msg.IsBinary=0 - Set msg.IsHTML=1 // Set IsHTML to 1 if email uses HTML - - If tHasResults { - - // Add attachment - Do ##class(PivotSubscriptions.Utility).WriteEmail(pName, msg, tableStatus) - - // if table is too large, then just attach Excel instead - If ((pFormat = "PDF") && (tableStatus)) { - Set tFilename = $EXTRACT(tFilename,1,$LENGTH(tFilename)-3) _ "pdf" - Do ##class(%DeepSee.Utils).%ExportPDFToFile(tFilename,.pParms) - } ElseIf 'tableStatus { - // Check if both configuration settings for admin email is valid before sending error message - If validAdminEmail { - Do ##class(PivotSubscriptions.Utility).SendErrorMessage(pPivot,^PivotSubscriptions.Settings("AdminEmail"),pName) - } - } - - Set status=msg.AttachFile("",tFilename) - - If $$$ISERR(status) { - Do $System.Status.DisplayError(status) - Quit $$$ERROR() - } - } Else { - Do ##class(PivotSubscriptions.Utility).WriteEmailHeader(msg) - Do msg.TextData.WriteLine("No data for requested pivot.") - Do ##class(PivotSubscriptions.Utility).WriteEmailFooter(msg) - } - - // iterate through all subscribers and send emails to each individually - For count=1:1:$l(pEmails,",") { - Set tEmail=$p(pEmails,",",count) - Do msg.To.SetAt(tEmail,1) - - // Send email - Set tSC=server.Send(msg) - } - - If tHasResults { - // Delete file - Do ##class(%File).Delete(tFilename) - } - } - - Quit tSC -} - -/// This method is called each time a new subscription is created. It will create or update the task as needed -ClassMethod ConfigureTask() As %Status -{ - Set tSC=$$$OK - //Does task exist? If so, update. Else, create - Set tFullName=..#TaskName_" - "_$NAMESPACE - Set tTaskID=##class(%SYS.Task).FindId(tFullName) - If tTaskID="" { - // Task is not present, need to create one - Set tTask=##class(%SYS.Task).%New() - Set tTask.Name=tFullName - Set tTask.NameSpace=$NAMESPACE - } Else { - // Task has already been defined - Quit tSC - } - - Set tTask.TaskClass="PivotSubscriptions.Task" - Set tTask.RunAsUser="_SYSTEM" - Set tTask.Description="Executes PivotSubscriptions Task" - - // Set schedule according to passed in parameters - Set tTask.TimePeriod=0 - Set tTask.TimePeriodEvery=1 - Set tTask.TimePeriodDay="" - - // Build runs at most once every day - Set tTask.DailyFrequency=1 - Set tTask.DailyFrequencyTime=0 - Set tTask.DailyIncrement=15 - Set tTask.DailyStartTime=0 - Set tTask.DailyEndTime=0 - - // The task should be operational at the next available build time - Set tSC=tTask.StartDateSet(+$h) - - Set tSC=tTask.%Save() - Quit tSC -} - -} +Parameter TaskName = "Pivot Subscriptions Task"; + +Method OnTask() As %Status +{ + Set tSC=$$$OK + + // Construct current day and time for query + Set tDayOfWeek=$ZDATE($HOROLOG,10) + Set tHour=$PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1) + Set tMinute=$PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2) + + If $G(^PivotSubscriptions.Settings("TestEnv")) { + // Ignore minute for testing purposes + // This will allow the task to be run on demand and send emails immediately + // Leaving DayOfWeek and Hour so the scheduled task does not spam emails + Set tRS=##class(%SQL.Statement).%ExecDirect(,"SELECT Emails,Name,Pivot,Format,DayOfWeek,""Hour"",""Minute"" FROM PivotSubscriptions.Subscription WHERE DayOfWeek[? AND ""Hour""=?",tDayOfWeek,tHour) + } Else { + Set tRS=##class(%SQL.Statement).%ExecDirect(,"SELECT Emails,Name,Pivot,Format,DayOfWeek,""Hour"",""Minute"" FROM PivotSubscriptions.Subscription WHERE DayOfWeek[? AND ""Hour""=? AND ""Minute""=?",tDayOfWeek,tHour,tMinute) + } + + // Loop through Subscription results and send emails. + While tRS.%Next() { + Set tEmails=tRS.%Get("Emails") + Set tPivot=tRS.%Get("Pivot") + Set tFormat=tRS.%Get("Format") + Set tDayOfWeek=tRS.%Get("DayOfWeek") + Set tHour=tRS.%Get("Hour") + Set tMinute=tRS.%Get("Minute") + Set tName=tRS.%Get("Name") + + Set tSC = ##class(PivotSubscriptions.Task).SendSubscription(tPivot,tEmails,tFormat,tDayOfWeek,tHour,tMinute,tName) + } + + Quit tSC +} + +ClassMethod SendSubscription(pPivot As %String, pEmails As %String, pFormat As %String, pDayOfWeek, pHour, pMinute, pName) As %Status +{ + Set tSC=$$$OK + + Set tSC=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName, .pEvent) + If $$$ISERR(tSC) Quit tSC + + If pName="" { + Set pName=$E(pPivot,1,*-6) + } + + Try { + Set tSC=##class(PivotSubscriptions.Task).SendEmail(pPivot,pEmails,pFormat,pName) + } Catch ex { + Set tSC=ex.AsStatus() + } + // Update send event with status and end time + Set tSC=pEvent.LogUpdate(tSC) + If $$$ISERR(tSC) Quit tSC + + If '(##class(PivotSubscriptions.Utility).CheckTable(pName)) { + Set tSC=##class(PivotSubscriptions.EventLog).LogEvent("tableError", $username, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName) + If $$$ISERR(tSC) Quit tSC + } + + Quit tSC +} + +ClassMethod SendEmail(pPivot As %String, pEmails As %String, pFormat As %String, pName As %String) As %Status +{ + Set tSC=$$$OK + Set tFilename="" + + Set mdx=##class(%DeepSee.Utils).%GetMDXFromPivot(pPivot,.tSC,0) + + // Execute MDX to see if there are results + Set tHasResults=0 + Set tRS=##class(%DeepSee.ResultSet).%New() + Do tRS.%PrepareMDX(mdx) + Do tRS.%Execute() + If tRS.%Query.queryType="DRILLTHROUGH" { + If tRS.listingRows>0 { + Set tHasResults=1 + } + } Else { + If tRS.%GetGrandTotal()'=0 { + Set tHasResults=1 + } + } + + // Only generate file if requested pivot has results + If tHasResults { + Set pParms("TITLE")=pName + Set pParms("SUBTITLE")=$E(pPivot,1,*-6)_". Report generated on "_$zd($h,6) + Set pParms("MDX")=mdx + + Set tFilename=$replace($zstrip(pName,"*PC'W",,"/")_" - "_$zd($h,6),"/","-")_".xls" + Set tSC=##class(%DeepSee.Utils).%ExportExcelToFile(tFilename,.pParms) + } + If $$$ISERR(tSC) Quit tSC + + // Generate email + If tSC { + // check whether the table generated is too wide/truncated AND whether the table has data + Set tableStatus=##class(PivotSubscriptions.Utility).CheckTable(pName) + + Set server=##class(%Net.SMTP).%New() + Set server.smtpserver=##class(%SYS.Task.Config).GetData("MailServer") + Set msg=##class(%Net.MailMessage).%New() + Set msg.From="PivotSubscriptions" + + Set validAdminEmail=##class(PivotSubscriptions.Utility).CheckConfigurationGlobal("AdminEmail") + + If validAdminEmail { + Set msg.ReplyTo=^PivotSubscriptions.Settings("AdminEmail") + } + + // Remove ".pivot" extension for subject + Set msg.Subject=pName + Set msg.IsBinary=0 + Set msg.IsHTML=1 // Set IsHTML to 1 if email uses HTML + + If tHasResults { + + // Add attachment + Do ##class(PivotSubscriptions.Utility).WriteEmail(pName, msg, tableStatus) + + // if table is too large, then just attach Excel instead + If ((pFormat = "PDF") && (tableStatus)) { + Set tFilename = $EXTRACT(tFilename,1,$LENGTH(tFilename)-3) _ "pdf" + Do ##class(%DeepSee.Utils).%ExportPDFToFile(tFilename,.pParms) + } ElseIf 'tableStatus { + // Check if both configuration settings for admin email is valid before sending error message + If validAdminEmail { + Do ##class(PivotSubscriptions.Utility).SendErrorMessage(pPivot,^PivotSubscriptions.Settings("AdminEmail"),pName) + } + } + + Set status=msg.AttachFile("",tFilename) + + If $$$ISERR(status) { + Do $System.Status.DisplayError(status) + Quit $$$ERROR() + } + } Else { + Do ##class(PivotSubscriptions.Utility).WriteEmailHeader(msg) + Do msg.TextData.WriteLine("No data for requested pivot.") + Do ##class(PivotSubscriptions.Utility).WriteEmailFooter(msg) + } + + // iterate through all subscribers and send emails to each individually + For count=1:1:$l(pEmails,",") { + Set tEmail=$p(pEmails,",",count) + Do msg.To.SetAt(tEmail,1) + + // Send email + Set tSC=server.Send(msg) + } + + If tHasResults { + // Delete file + Do ##class(%File).Delete(tFilename) + } + } + + Quit tSC +} + +/// This method is called each time a new subscription is created. It will create or update the task as needed +ClassMethod ConfigureTask() As %Status +{ + Set tSC=$$$OK + //Does task exist? If so, update. Else, create + Set tFullName=..#TaskName_" - "_$NAMESPACE + Set tTaskID=##class(%SYS.Task).FindId(tFullName) + If tTaskID="" { + // Task is not present, need to create one + Set tTask=##class(%SYS.Task).%New() + Set tTask.Name=tFullName + Set tTask.NameSpace=$NAMESPACE + } Else { + // Task has already been defined + Quit tSC + } + + Set tTask.TaskClass="PivotSubscriptions.Task" + Set tTask.RunAsUser="_SYSTEM" + Set tTask.Description="Executes PivotSubscriptions Task" + + // Set schedule according to passed in parameters + Set tTask.TimePeriod=0 + Set tTask.TimePeriodEvery=1 + Set tTask.TimePeriodDay="" + + // Build runs at most once every day + Set tTask.DailyFrequency=1 + Set tTask.DailyFrequencyTime=0 + Set tTask.DailyIncrement=15 + Set tTask.DailyStartTime=0 + Set tTask.DailyEndTime=0 + + // The task should be operational at the next available build time + Set tSC=tTask.StartDateSet(+$h) + + Set tSC=tTask.%Save() + Quit tSC +} + +} diff --git a/PivotSubscriptions/Utility.cls b/PivotSubscriptions/Utility.cls index e75231b..0d44e78 100644 --- a/PivotSubscriptions/Utility.cls +++ b/PivotSubscriptions/Utility.cls @@ -158,7 +158,7 @@ ClassMethod WriteEmail(pName As %String, pMsg As %Net.MailMessage, pTableStatus) ClassMethod SendErrorMessage(pPivot As %String, pEmail As %String, pName As %String) As %Status { - Set tLog=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, $ZDATE($HOROLOG,10), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2), "", pEmail, pName) + Set tLog=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, $ZDATE($HOROLOG,10), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2), "", pEmail, pName, .pEvent) If $$$ISERR(tLog) Quit tLog @@ -183,6 +183,7 @@ ClassMethod SendErrorMessage(pPivot As %String, pEmail As %String, pName As %Str // Send email Set tSC=server.Send(msg) + Set tSC=pEvent.LogUpdate(tSC) Quit tSC } From 01f0609a46bed34c3c83d50428013f4f41ca423f Mon Sep 17 00:00:00 2001 From: psteiwer Date: Fri, 14 Feb 2020 12:13:40 +0100 Subject: [PATCH 04/37] Split send Events into two different event types New Events are now sendError and sendSubscription --- PivotSubscriptions/EventLog.cls | 2 +- PivotSubscriptions/Task.cls | 2 +- PivotSubscriptions/Utility.cls | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PivotSubscriptions/EventLog.cls b/PivotSubscriptions/EventLog.cls index 6f281f9..fa114b9 100644 --- a/PivotSubscriptions/EventLog.cls +++ b/PivotSubscriptions/EventLog.cls @@ -6,7 +6,7 @@ Class PivotSubscriptions.EventLog Extends %Persistent * Only possible values are creation, update, deletion, send, and tableError */ /// Event Type covers: creation, update, deletion and sent email subscriptions -Property EventType As %String(VALUELIST = ",creation,update,deletion,send,tableError"); +Property EventType As %String(VALUELIST = ",creation,update,deletion,sendSubscription,sendError,tableError"); Property StartTime As %TimeStamp [ InitialExpression = {$zdt($h, 3, 1)} ]; diff --git a/PivotSubscriptions/Task.cls b/PivotSubscriptions/Task.cls index e8e3b09..b3afd21 100644 --- a/PivotSubscriptions/Task.cls +++ b/PivotSubscriptions/Task.cls @@ -41,7 +41,7 @@ ClassMethod SendSubscription(pPivot As %String, pEmails As %String, pFormat As % { Set tSC=$$$OK - Set tSC=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName, .pEvent) + Set tSC=##class(PivotSubscriptions.EventLog).LogEvent("sendSubscription", $username, pPivot, pDayOfWeek, pHour, pMinute, pFormat, pEmails, pName, .pEvent) If $$$ISERR(tSC) Quit tSC If pName="" { diff --git a/PivotSubscriptions/Utility.cls b/PivotSubscriptions/Utility.cls index 0d44e78..9f273ef 100644 --- a/PivotSubscriptions/Utility.cls +++ b/PivotSubscriptions/Utility.cls @@ -158,7 +158,7 @@ ClassMethod WriteEmail(pName As %String, pMsg As %Net.MailMessage, pTableStatus) ClassMethod SendErrorMessage(pPivot As %String, pEmail As %String, pName As %String) As %Status { - Set tLog=##class(PivotSubscriptions.EventLog).LogEvent("send", $username, pPivot, $ZDATE($HOROLOG,10), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2), "", pEmail, pName, .pEvent) + Set tLog=##class(PivotSubscriptions.EventLog).LogEvent("sendError", $username, pPivot, $ZDATE($HOROLOG,10), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",1), $PIECE($ZTIME($PIECE($HOROLOG,",",2),2),":",2), "", pEmail, pName, .pEvent) If $$$ISERR(tLog) Quit tLog From 6e00abf77df167170f5250e8ecf2bbfeb4e363ed Mon Sep 17 00:00:00 2001 From: psteiwer Date: Fri, 14 Feb 2020 12:17:37 +0100 Subject: [PATCH 05/37] Modify create and delete event type names --- PivotSubscriptions/EventLog.cls | 2 +- .../UI/Dialog/EditSubscription.cls | 398 +++++++++--------- PivotSubscriptions/UI/SubscriptionManager.cls | 6 +- 3 files changed, 203 insertions(+), 203 deletions(-) diff --git a/PivotSubscriptions/EventLog.cls b/PivotSubscriptions/EventLog.cls index fa114b9..94940ba 100644 --- a/PivotSubscriptions/EventLog.cls +++ b/PivotSubscriptions/EventLog.cls @@ -6,7 +6,7 @@ Class PivotSubscriptions.EventLog Extends %Persistent * Only possible values are creation, update, deletion, send, and tableError */ /// Event Type covers: creation, update, deletion and sent email subscriptions -Property EventType As %String(VALUELIST = ",creation,update,deletion,sendSubscription,sendError,tableError"); +Property EventType As %String(VALUELIST = ",create,update,delete,sendSubscription,sendError,tableError"); Property StartTime As %TimeStamp [ InitialExpression = {$zdt($h, 3, 1)} ]; diff --git a/PivotSubscriptions/UI/Dialog/EditSubscription.cls b/PivotSubscriptions/UI/Dialog/EditSubscription.cls index 097f067..c5836c7 100644 --- a/PivotSubscriptions/UI/Dialog/EditSubscription.cls +++ b/PivotSubscriptions/UI/Dialog/EditSubscription.cls @@ -1,199 +1,199 @@ -Class PivotSubscriptions.UI.Dialog.EditSubscription Extends %DeepSee.UI.Dialog.standardDialog -{ - -/// Class name of application this page belongs to. -Parameter APPLICATION; - -/// Displayed name of this page. -Parameter PAGENAME; - -Parameter DOMAIN = "PivotSubscriptions"; - -Property pivotName As %ZEN.Datatype.string(ZENURL = "PIVOTNAME"); - -Property SubscriptionId As %ZEN.Datatype.integer(ZENURL = "SUBSCRIPTIONID"); - -Parameter APPLYBUTTON = 0; - -/// This Style block contains page-specific CSS style definitions. -XData Style -{ - -} - -/// This XML block defines the contents of this page. -XData dialogBody [ XMLNamespace = "http://www.intersystems.com/zen" ] -{ - -