A Power BI dashboard for monitoring the data quality of regulatory information (RIM) in a pharmaceutical company: QC checks run across Registrations, Submissions, Products and Documents, the deviations they raise, and how fast those deviations get corrected.
This is a portfolio project. None of it is real.
- The data is 100% synthetic. The 12,000-row export in
data/raw/was generated for this project. It is not an extract from any real system and contains no real regulatory records. - "Cortonis Pharma" is a fictional company. It does not exist. The persona shown in the report (
William User / william.user@cortonis.com), the team names and the org structure are all invented. - The QC checks are invented. The 26 checks in this project (see below) were written from scratch to look plausible. They do not necessarily reflect the checks, thresholds, priorities or risk ranking that a real pharma regulatory / data-governance function would use. Treat them as an illustrative catalogue, not a recommendation.
Regulatory Information Management (RIM) systems hold the master data that authorises a company to sell a product in a country: registrations, submissions, applications, health-authority correspondence, controlled documents. When that data drifts β an orphaned registration, a duplicate submission ID, an approval dated before its submission β the business risk is real (missed renewals, non-compliant filings, audit findings).
This project models a recurring QC-check process over that data and builds the dashboard a data-governance lead would use to run it:
- Overview β How compliant is our regulatory data overall?
- Findings β the check-level list of current findings, each linked to its record.
- Process & Checks β Which processes and fields generate the most findings?
- Quality Deviations β Which findings are still open, and how fast do we close them?
- EDA (hidden) β free pivot tables for ad-hoc exploration.
Headline KPIs (compliance rate, current findings, open and aging deviations, MTTR, right-first-time), monthly check volume by compliance status, and a compliance breakdown that pivots across dimensions.
Every current finding with its deviation, DQ dimension, country, criticality, RIM process area, check and product, plus a link to the source record.
Compliance rate and non-compliant checks per RIM process area and check, average findings detected per month, and detected vs corrected findings over time.
Deviation register with correction progress, resolution-time histogram (mean vs median time to resolve), and the open-deviation backlog by RIM process area.
The single flat table this dashboard consumes (data/raw/data export quality dashboard (fictional v2).csv) is the target shape β the clean, check-level fact table you would want in order to monitor data quality and build a dashboard on top of it. One row = one QC check executed against one record, with its outcome, its deviation (if any), the detection and correction dates, and the process / product / country / team it belongs to.
Producing that table is the actual hard part, and it is out of scope here. In a real setup you would have to:
- pull records out of one or more RIM systems and their satellites (submissions archive, document management, product master data);
- reconcile entities across those systems (a registration in one, its documents in another, its submissions in a third);
- encode each QC rule as executable logic and run it on a schedule;
- open, route, track and close deviations, and capture the correction date.
This repository starts after all of that: it assumes the check-level table already exists and focuses on the semantic model and the report. The data-engineering pipeline that would build the table for real is intentionally not included.
The model is named against the DIA RIM Reference Model V2.0 (DIA RIM Working Group, 2026 β copy in docs/dia standards/), the industry's vendor-neutral reference framework for regulatory information, not against any single RIM product's object model. The QC checks are phrased the same way (e.g. "Broken link Submission β Application β Registration", "Registration without linked Health Authority").
| In this project | DIA RIM Reference Model V2.0 | Note |
|---|---|---|
Object = Submission |
Submission | exact object name |
Object = Registration |
License-Registration | DIA's full object name; "Registration" is the common industry short form |
Object = Product |
Medicinal Product (in the Product Family β Global Product β Medicinal Product hierarchy) | kept as the umbrella term |
Object = Document |
Content / Submission Content | documents are formally scoped to the sisterDIA EDM Reference Model; "Document" is the term every RIM/DMS platform shares |
Application, Health Authority, Content Plan, Product Family, Active Substance, Procedure Type, Country, Region |
Application Β· Health Authority Β· Submission Content Plan Β· Product Family Β· Substance / "INN (generic name)" Β· Application Procedure Type Β· Country Β· Country.Regions | all DIA object / attribute names |
Process β {Submission / Registration / Product Management, Document Control} |
regulatory business-process capability names | standard RIM capability taxonomy, not vendor-specific |
Dimension β {Completeness, Uniqueness, Validity, Accuracy, Consistency, Timeliness, Referential Integrity} |
not a DIA concept | the sixDAMA-DMBOK data-quality dimensions, plus Referential Integrity |
The Registration / Submission / Application trio is shared vocabulary between the DIA model and every major RIM vendor, so the same fields map β with only a rename β onto:
- Veeva Vault RIM (Registrations / Submissions / Submissions Archive)
- Ennov RIM
- ArisGlobal LifeSphere RIM
- Calyx RIM
- Generis CARA RIM
- EXTEDO RIMS
- Lorenz (drugTrack / docuBridge)
- Samarind RMS
- Amplexor / Acolad Life Sciences RIM
No feature of the report depends on a vendor-specific schema, and no term used here is unique to Veeva Vault RIM.
Known wording drift from the strict DIA vocabulary (kept for readability, no impact on portability): Submission ID β DIA Submission Number; Registration Number β DIA License Number; Type of Product carries therapeutic classes and would be Therapeutic Area in DIA (and Antipiretics should read Antipyretics).
Synthetic β data/raw/data export quality dashboard (fictional v2).csv
| Rows | 12,000 (one per QC check) |
| Detection dates | 2023-09-01 β 2026-08-20 |
| Countries | 134, grouped into 5 regions |
| Teams | 20 (4 functions Γ 5 regions) |
| Distinct checks | 26, across 7 data-quality dimensions |
| Processes | 4 β Submission Management, Registration Management, Product Management, Document Control |
| Products | 240, across 6 therapeutic classes |
| Findings | ~826 detected / ~833 corrected / ~10,341 with no finding |
| Field | Description |
|---|---|
Check Name |
The QC rule that was run |
Dimension |
Completeness, Referential Integrity, Uniqueness, Consistency, Timeliness, Validity, Accuracy |
Object / Field |
Regulatory object and field the rule targets |
Process |
Business process the check belongs to |
Criticality |
Critical / Major / Minor |
Check Status |
No finding Β· Finding detected Β· Finding corrected |
Compliance Status |
Compliant / Non compliant (derived from Check Status) |
Deviation # |
Deviation identifier, when a finding is raised |
Detection Date / Compliance Date / Created Date |
Finding QC checksΒ lifecycle dates |
Product / Type of Product |
Affected product and its therapeutic class |
Country / Region |
Where the affected record is registered |
Team |
Team responsible for the process in that region |
Record ID / Finding ID |
Record and finding keys |
The 26 invented checks, by process:
- Registration Management β Orphaned Registration after Product merge/deletion Β· Duplicate Registration Number within same country/product Β· Registration without linked Product Β· Registration without linked Health Authority Β· Registration linked to archived/inactive Health Authority Β· Registration status vs linked document status mismatch Β· Renewal completed but entered beyond SOP-defined entry window
- Submission Management β Submission without linked Application Β· Broken link Submission β Application β Registration Β· Duplicate Submission ID from bulk import Β· Submission missing Content Plan Β· Submission tracking status inconsistent with Application status Β· Submission event recorded beyond SOP-defined entry window Β· Approval date earlier than submission date Β· Approval date in metadata mismatched vs Health Authority approval letter Β· Health Authority confirmation date mismatch vs recorded date
- Product Management β Product record missing INN/generic name Β· Product name/spelling inconsistent across linked records Β· Duplicate Product/Country/Procedure combination Β· Deprecated reference value still in use Β· Country/Health Authority outside reference model
- Document Control β Multiple documents simultaneously marked "Approved" Β· Approved document missing effective date Β· Approved document not uploaded/indexed within SOP-defined timeframe Β· Document language inconsistent with "Language" metadata field Β· Document orphaned after Registration archival
Star schema, Import mode, one flat source table split into a fact and three dimensions in Power Query.
fact_qcchecks βββ¬ββ dim_process (Check Name β Process, Criticality, Dimension, Field, Object, Team) via "Check Name - Country"
βββ dim_countries (Country β Region)
βββ dim_products (Product β Type of Product)
βββ Detection / Compliance / Created Date (auto date tables)
X-Axis Switch field parameter β lets most charts pivot their axis across 13 dimensions
| Measure | Definition |
|---|---|
Total Checks |
DISTINCTCOUNT(fact_qcchecks[Record ID]) |
Compliant Checks / Non-Compliant Checks |
Total Checks filtered on Compliance Status |
Compliance Rate % |
DIVIDE([Compliant Checks], [Total Checks]) |
Open Deviations |
distinctDeviation # where Check Status = "Finding detected" |
Deviations Corrected |
checks whereCheck Status = "Finding corrected" |
Total Deviations |
distinctDeviation # where Check Status <> "No finding" |
Deviation Rate % |
DIVIDE([Total Deviations], [Total Checks]) |
Correction Rate % |
DIVIDE([Deviations Corrected], [Total Deviations]) |
Avg Days to Correct |
AVERAGEX of DATEDIFF(Detection, Compliance, DAY) over corrected findings |
Critical Open Deviations |
Open Deviations where Criticality = "Critical" |
Right First Time % |
share of checks whereCompliance Date = Created Date |
Note:
Non-Compliant ChecksequalsOpen Deviationsby construction βCompliance Statusis fully derived fromCheck Statusin the synthetic data.Deviation Rate %and1 β Compliance Rate %are not the same thing: the first counts every historical deviation (including corrected ones), the second is a current-state snapshot.
Data-Quality/
βββ data/
β βββ raw/ # the synthetic check-level export (source of the model)
β βββ processed/ # (unused β no transformation layer in this project)
β βββ sample/ # tiny placeholder sample
βββ dashboard/
β βββ powerbi/ # Power BI project in PBIP format (JSON + TMDL, diffable)
β β βββ Data Quality Dashboard.pbip
β β βββ Data Quality Dashboard.Report/ # pages & visuals (PBIR)
β β βββ Data Quality Dashboard.SemanticModel/ # model & Power Query M (TMDL)
β βββ assets/ # page-background source images
β βββ tableau/ # (unused)
βββ docs/ # references & bibliography (+ data-dictionary / methodology templates)
βββ sql/ src/ scripts/ notebooks/ # scaffolding only β see "out of scope" above
βββ reports/screenshots/ # report page captures (shown above)
βββ LICENSE
The sql/, src/, scripts/ and notebooks/ folders are repo scaffolding kept from a template. They hold no logic here β the data-operations work they would contain is deliberately out of scope (see above).
- Clone the repo.
- Open
dashboard/powerbi/Data Quality Dashboard.pbipin Power BI Desktop (with Power BI Project (.pbip) save format enabled). - The model imports from the CSV in
data/raw/via an absolute path inexpressions.tmdlβ update that path to your local clone, then Refresh.
Full bibliography β DIA RIM Reference Model V2.0, data-quality frameworks (DAMA-DMBOK,
ISO 8000), the regulatory standards the checks assume (eCTD, IDMP, SPOR, INN), RIM
vendor references and build tooling β in docs/references.md.
MIT β see LICENSE.