Automating the distribution of Project Status Reports

mikereaves
Tera Expert

We'd like to establish a process for project managers(PM) to create project_status records and generate *.PDF versions of the reports using the workspace project status templates.

Ideally, the PM would:
navigate to the project workspace
select a project > status reports > create status report & complete fields
the report would be rendered according to the template

The PM could edit the report & when satisfied,
The PM would click a UI Action to email the status report in PDF format to [watch list, PM, etc.]

Any recommendations or guidance would be greatly appreciated.
I'm comfortable coding, but before I invent a wheel... have you done anything like this?

Thanks,
Mike Reaves



4 REPLIES 4

maliksneha9
Mega Sage

Hi, 

You can implement this in ServiceNow without reinventing too much by combining Project Status Reports, PDF generation, a UI Action, and a notification. A common approach looks like this, which I personally use:

 

1. Create the Status Report (Out-of-the-Box)

Project managers can already create status reports directly from Project Workspace:

Project Workspace → Select Project → Status Reports → Create Status Report

 

2. Generate a PDF Version of the Report

Once the report is ready, you can generate a PDF using the PDFGenerationAPI. A common approach is to render the report content as HTML and convert it to a PDF that is saved as an attachment on the status report record.

Server Side Script:-

var pdf = new sn_pdfgeneratorutils.PDFGenerationAPI();

var gr = new GlideRecord('pm_project_status');
if (gr.get(current.sys_id)) {

var html = "<h1>Project Status Report</h1>";
html += "<p>Status: " + gr.overall_status + "</p>";
html += "<p>Summary: " + gr.status_summary + "</p>";

pdf.convertToPDF(html, 'pm_project_status', gr.sys_id, 'Project_Status_Report.pdf');
}

 

3. Add a UI Action to Send the Report

Create a UI Action on the pm_project_status table (for example: Send Status Report). When clicked, it can generate the PDF and trigger an event to send the email.

 

4. Send the Email with the PDF

Create a custom event such as: project.status.report.email

Then configure a Notification triggered by that event.
Recipients could include: Project Manager, Watch List etc

mikereaves
Tera Expert

Thank you so much.
I'll give it a try.
FYI - the table for Project Status Reports is now project_status (not pm_project_status).
I've seen other folks mention the old table name too but Uncle Google told me:

While earlier versions or custom implementations might have referenced pm_project_status, the standard, out-of-the-box table used for reporting on projects is project_status.
<HTML>

https://www.google.com/search?q=ServiceNow+when+did+the+table+name+change+from+pm_project_status+to+...

mikereaves
Tera Expert

Thanks for this..., question where does the file created in step 2 get stored?
How would the notification attach the *.pdf file?

maliksneha9
Mega Sage

Hi @mikereaves ,

 

All the attachments always gets stored in sys_attachment table. The PDF will get automatically stored as an attachment in the sys_attachment table.

 

  • Table Name: pm_project_status
  • Table Sys ID: gr.sys_id

File Name: Project_Status_Report.pdf

 

Approach 1: Attach existing record attachments

Since the PDF is already attached to the record:

In Notification:

  • Go to Notification 
  • Check:
    • Include attachments

Result:

  • All attachments on the record (including your PDF) are sent automatically.

 

 

Approach 2: Attach via Script (More Control)

If you want to attach only that PDF or control logic:

In Notification, Email Script:

var attachmentGR = new GlideRecord('sys_attachment');
attachmentGR.addQuery('table_sys_id', current.sys_id);
attachmentGR.addQuery('table_name', 'pm_project_status');
attachmentGR.addQuery('file_name', 'Project_Status_Report.pdf');
attachmentGR.query();
while (attachmentGR.next()) {
email.addAttachment(attachmentGR.sys_id);
}
 
Trigger the notification - 
gs.eventQueue('project.status.report.email', current, current.sys_id, gs.getUserID());