Skip to content

PDP Intelligence Report — How It Works ​

UserStory1121. A monthly AI-written report that turns the previous month's Personal Development Plan (PDP) responses into management intelligence. It covers participation, safety, WIP / KPI pressure, fleet, operational issues, employee comments, themes, sentiment, health, risks, recommendations and a bottom line. It is read at the monthly management meeting (3rd Wednesday). It replaces a manual ChatGPT run over the exported Google Forms spreadsheet.


1. Pieces ​

PieceWhere
EndpointPOST /api/Forms/pdp/report/intelligence[?month=yyyy-MM] on WebAPI (FormsController), basic auth. Returns 202 and runs in the background
LogicWebAPI/Services/PDPIntelligenceReportService.cs
PDF layoutWebAPI/Services/PDPIntelligenceReportPdf.cs, on CommonFormsPdf/PdfCanvas (Table, Bullet)
Datadbo.ethFormPDPGetIntelligenceReportData (DbMigrations/Scripts/Programmable/Procedures/) via IFormsData.GetPDPIntelligenceReportData
PromptCommonAIModel/PromptTemplates/PDPIntelligenceReportPromptTemplate.md (embedded)
StorageContainer pdp-intelligence-reports in the forms storage account (Azure:FormsBlobStorage)
ViewerAdminPortal /view/forms/pdp-intelligence-reports/..., Ethos sign-in required (container allowlisted in FormsAttachmentService)
EmailPDPIntelligenceReportEmail.html (PDP email chrome), queued with IEmailMessageData.InsertHtmlMessage
Schedulen8n flow PDP Intelligence Report - Run

2. Schedule and period ​

  • n8n fires every Saturday at 7am. An IF node passes only days 11–17: the Saturday before the 3rd Wednesday, which always falls on the 15th–21st.
  • The report covers the previous calendar month in Melbourne time. ?month=yyyy-MM re-runs an earlier month.
  • A PDP counts for the month it was submitted (SubmittedDate, UTC). Drafts are ignored.
  • The endpoint returns at once because the AI call takes about a minute. That call runs under a 15-minute per-request timeout (AiRequest.Timeout). A synchronous call risked the ~230s App Service front-end timeout, and an n8n retry would then send the report twice. If the app restarts mid-run, that run is lost: re-trigger it with ?month=.

3. Who counts ​

  • Cohort = current employees, using the same filter as the PDP completion report (ethFormPDPGetEmployeesWithoutPDP: active Prime user, @ethosbuilding.com.au, not (CE), not in primeUsersExcluded, not the two report recipients). Plus former employees (Prime user no longer active) who had a PDP this financial year. They appear in the non-participation list as "(left business)" but are not in the participation-rate denominator.
  • Managers = anyone who is someone's manager in primeUsersManager (AdminPortal > Settings > Manager Relationships). Managers count towards participation, but their PDPs are not sent to the AI. Every analytical section therefore reflects workforce feedback only. The report does not say so.
  • PDP Completion by Manager (UserStory1946) is the old PDP completion report email (pdp/report/missing) folded in as a section after the non-participation list. It is the manager / employee / completed this month / last PDP table from ethFormPDPGetEmployeesWithoutPDP over the same month window. It lists current employees only, sorted by manager, with "No manager set" last.
  • Role for "participation by role" = the PDP type of the employee's latest submitted PDP. "Not yet classified" = has never had a PDP.

4. Counted vs interpreted ​

The service counts everything numeric, so the figures always reconcile: responses, unique participants, cohort, participation rate, by-role table, non-participant names, SWMS compliance (SWMSCompliance Yes of Yes/No) and schedule control (IsScheduleUpToDate Yes of Yes/No). Blank and N/A answers count as neither. Issue-theme frequencies are also counted from the employee names the AI lists.

The AI gets one object per non-manager PDP, holding employee, type, date, reviewing manager, left-business flag and the answered fields. Photos, identity fields and unasked checkboxes are dropped: every snapshot carries every checkbox as false, so only the PDP type that asks a checkbox sends it. The AI returns one JSON object with the narrative sections, which is deserialised into PDPReportAnalysis. Model = OpenAI:DefaultModel.

5. Output ​

  • {yyyy-MM}/{guid}_Ethos_PDP_Intelligence_Report_YYYY_MM.pdf, plus the full report as .json beside it for future trend dashboards. The GUID keeps a re-run from overwriting the copy an earlier email links to.
  • The email goes to PDPSummary:Recipient (pdp@ethosbuilding.com.au). PDPSummary:EmailOverride, when set, replaces it. Set the override everywhere but production, because the report names employees and their feedback.
  • About 10 pages for a month of ~25 PDPs. Empty sections keep their heading with "Nothing reported this month".

Not built: the action register (issue → owner → status carried month to month), and loading the JSON into a table for Metabase.