Skip to content

RdmpCohortBuildHealthBoardBreakdown plugin package (9.2.3)#2368

Open
mtinti wants to merge 3 commits into
HicServices:developfrom
mtinti:release/RdmpCohortBuildHealthBoardBreakdown
Open

RdmpCohortBuildHealthBoardBreakdown plugin package (9.2.3)#2368
mtinti wants to merge 3 commits into
HicServices:developfrom
mtinti:release/RdmpCohortBuildHealthBoardBreakdown

Conversation

@mtinti

@mtinti mtinti commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Proposed Change

Adds a self-contained package for the RdmpCohortBuildHealthBoardBreakdown plugin (RDMP 9.2.3), under
the new top-level RdmpCohortBuildHealthBoardBreakdown/ folder: the built .rdmp plugin, its source,
and install/usage notes. It ships the built plugin (for review and installation) rather than a
Rdmp.Core code merge; the full source is included under src/.

What the plugin does: reproduces the Cohort Builder's per-set / per-container count tree (the
FinalCount and cumulative running totals shown as UNION/INTERSECT/EXCEPT are applied), split by
Scottish health board, plus the unfiltered national total, as a wide CSV.

How it works: it builds the cohort once (which populates RDMP's query cache), then recomposes every
count point purely from the cached per-set identifier tables and splits each by
SHARE_Demography.Region with one GROUP BY per node. There is no per-board rebuild, and no
source-catalogue hits after the single build (so it is cross-server safe). It requires a query-caching
server, and the demography catalogue on the same server as the cache.

Output: a wide CSV. One row per count point (name written once), a Metric column (Final and
Cumulative), a Total column (national), one column per Scottish board, then Other (present
non-Scottish or unmapped region codes) and NotKnown (not in demography, or null region). The column
header is repeated above a % of final cohort row. Boards plus Other plus NotKnown reconcile to Total
on every row.

Contents (RdmpCohortBuildHealthBoardBreakdown/): RdmpCohortBuildHealthBoardBreakdown.rdmp,
README.md, INSTALL.md, and src/ (command, report, health-board lookup, UI hook, csproj, nuspec).

Validation: verified end-to-end against a deterministic synthetic fixture (a top EXCEPT over an
inclusion INTERSECT minus four exclusion sets, with the cohort partitioned across 3 boards). Every
national and per-board count and cumulative is asserted cell-by-cell, the unfiltered column equals
RDMP's own CohortCompiler counts, and the boards sum to national at every node.

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New Feature (non-breaking change which adds functionality)
  • Breaking Change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation-Only Update
  • Other (if none of the other choices apply)

Checklist

By opening this PR, I confirm that I have:

  • Ensured that the PR branch is in sync with the target branch (i.e. it is automatically merge-able). Additive (one new folder).
  • Created or updated any tests if relevant. NUnit unit and DB-integration tests exist with the source (Rdmp.Core.Tests), validated against the fixture described in the source.
  • Have validated this change against the Test Plan. Validated against the deterministic synthetic fixture instead.
  • Requested a review by one of the repository maintainers. Draft, opened for visibility.
  • Have written new documentation or updated existing documentation to detail any new or updated functionality and how to use it (README.md, INSTALL.md).
  • Have added an entry into the changelog. Not applicable for this plugin-package PR.

Self-contained package for the cohort-build health-board breakdown plugin:
the built .rdmp, install/usage notes, plugin source, and design + technical
documentation. Splits the Cohort Builder's per-step count tree by Scottish
health board (wide CSV: Metric, Total, per-board columns, Other, NotKnown, and
a % of final cohort row). Cache-only recompose, validated against a
deterministic synthetic fixture.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0169JCnaL3fhhZjseDx2XXT2
mtinti and others added 2 commits July 1, 2026 15:41
Keep the package to the built .rdmp + INSTALL + README + source. Design and
technical docs remain on the proposals branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0169JCnaL3fhhZjseDx2XXT2
@mtinti mtinti marked this pull request as ready for review July 1, 2026 20:39

@JFriel JFriel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change would be a better tagret for a plugin, rather than core RDMP. Can discuss HIC owned plugins via teams


namespace RdmpCohortBuildHealthBoardBreakdown;

public class CohortBuildHealthBoardBreakdownPluginUserInterface : PluginUserInterface

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PluginUserInterface is really for use by plugins, not code that has access to the RDMP internals. If this is something you want to keep as a plugin, it may be best to create it as a standalone outside of the RDMP codebase, or target the chodechange against the HIC specific Plugin Codebase (can share seperatly). If you want to keep in in core RDMP, this functionality is best moved to the ContetxStripMenu or the standard RightClick options function

@@ -0,0 +1,24 @@
// Surfaces the cohort build health board breakdown in the RDMP desktop GUI (right-click a cohort

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should be in the existing directory structure. Something like RDMP.Core/CohortCreation/Aggregates or similar

public const string PercentMetric = "% of final cohort";

/// <summary>One count point of the build tree with its per-region counts (known boards only).</summary>
public sealed class NodeBreakdown

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put these nested classes into their own file

CohortIdentificationConfiguration cic,
[DemandsInitialization("CSV file to write. Defaults to <cic>-build-healthboard.csv in the current directory")]
FileInfo toFile = null,
[DemandsInitialization("Demography catalogue holding the region column", DefaultValue = "SHARE_Demography")]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cant use this as a default value in the RDMP codebase. Probably shouldn't have a default value

private readonly Dictionary<int, (string fqn, string col)> _setCacheTable = new();
private readonly Dictionary<(bool isContainer, int id), (int final, int? cumulative)> _baseline = new();

public ExecuteCommandExportCohortBuildHealthBoardBreakdown(IBasicActivateItems activator,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth making this more geenric i.e. ExportCohortBuildBreakDownByGroups or similar

CohortIdentificationConfiguration cic,
[DemandsInitialization("CSV file to write. Defaults to <cic>-build-healthboard.csv in the current directory")]
FileInfo toFile = null,
[DemandsInitialization("Demography catalogue holding the region column", DefaultValue = "SHARE_Demography")]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should pass in a catalogue, not a string. It can also be mapped from the cli like Catalogue:1234

[DemandsInitialization("Demography catalogue holding the region column", DefaultValue = "SHARE_Demography")]
string demographyCatalogue = "SHARE_Demography",
[DemandsInitialization("Region (health board cipher) column on the demography catalogue", DefaultValue = "Region")]
string regionColumn = "Region",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should pass in a ColumnInfo

if (parent != null && indexInParent > 0 && cCum.HasValue)
cCumByRegion = RunRegionCounts(CumulativeSql(parent, indexInParent));

nodes.Add(new CohortBuildHealthBoardBreakdownReport.NodeBreakdown

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add a constructor to nodebreakdown that maps the key/values rather than have to manually map them here and further down


private IReadOnlyDictionary<string, int> RunRegionCounts(string idListSql)
{
var sql =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RMDP supports multible db types (sql,postgres,oracle). This SQL will need to be rewritten using FansiSQL

public const string UnknownNode = "Unknown";

// keyed by the single-letter Region cipher held in SHARE_Demography.Region
private static readonly Dictionary<string, HealthBoard> ByRegion = new(System.StringComparer.OrdinalIgnoreCase)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be in RMDP and if something like this is required, it should reference a user-defined lookup

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants