Skip to content

Enable importing of BNF data releases using the new ODP CSV format - #3177

Open
KatieB5 wants to merge 2 commits into
mainfrom
KatieB5/get-bnf-updates-from-odp-api
Open

Enable importing of BNF data releases using the new ODP CSV format#3177
KatieB5 wants to merge 2 commits into
mainfrom
KatieB5/get-bnf-updates-from-odp-api

Conversation

@KatieB5

@KatieB5 KatieB5 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Addresses steps 1 and 2 listed in #3167

Previously, we imported BNF data from ZIP archives downloaded from the NHSBSA Information Services Portal (ISP).
The ISP is no longer available, and BNF releases are now published as CSV files via the NHSBSA Open Data Portal (ODP).

Due to this change, our existing BNF data import process no longer works, and we cannot update the BNF data in production. This is blocking a user’s research work (Slack thread).

This PR makes the minimum updates required to support importing the latest BNF releases from the ODP
while preserving the existing import workflow described in coding_systems/bnf/README.md.

Importer updates

  • import BNF releases directly from CSV files
  • normalise CSV headers to support the new ODP column naming convention
  • remove ZIP extraction from the BNF import path

Test updates

  • update the BNF import fixture to match the test CSV data to the new ODP CSV format
  • update the import tests to use the new CSV fixture
**Local testing**

Assess current local state of BNF data:

What does the most current release look like:
just manage shell

>>> from coding_systems.versioning.models import CodingSystemRelease
>>> 
>>> latest = (
...     CodingSystemRelease.objects
...     .filter(coding_system="bnf")
...     .latest("valid_from")
... )
>>> print(latest)
86 (2024-09-02) (valid from 2024-09-02)
>>> print(latest.release_name)
86 (2024-09-02)
>>> print(latest.valid_from)
2024-09-02
>>> print(latest.import_ref)
20240902_1725264234995_BNF_Code_Information.zip
>>> print(latest.state)
ready
>>> print(latest.database_alias)
bnf_86-2024-09-02_20240902

Which BNF releases do I have available locally?
>>> for release in (
...     CodingSystemRelease.objects
...     .filter(coding_system="bnf")
...     .order_by("-valid_from")
... ):
...     print(
...         release.release_name,
...         release.valid_from,
...         release.state,
...         release.database_alias,
...     )
... 

86 (2024-09-02) 2024-09-02 ready bnf_86-2024-09-02_20240902
86 (2024-05-02) 2024-05-02 ready bnf_86-2024-05-02_20240502
86 (2024-01-01) 2024-01-01 ready bnf_86-2024-01-01_20240101
84 (2023-11-01) 2023-11-01 ready bnf_84-2023-11-01_20231101
84 (2023-09-01) 2023-09-01 ready bnf_84-2023-09-01_20230901
84 (2023-05-02) 2023-05-02 ready bnf_84-2023-05-02_20230502
84 (2023-02-01) 2023-02-01 ready bnf_84-2023-02-01_20230201
82 (2022-11-01) 2022-11-01 ready bnf_82-2022-11-01_20221101
unknown 1900-01-01 ready bnf_unknown_19000101

Run local dev server: just run

Check what we can see for MontyTest3 BNF codelist in the browser:
Screenshot from 2026-07-23 08-18-19

Locally run the import:
python manage.py import_coding_system_data bnf /home/katie/opencodelists-bnf-data/bnf_code_current_202503_version_88.csv --release "88 (2025-03-01)" --valid-from 2025-03-01 --import-ref bnf_code_current_202503_version_88.csv

Setting up database...
Operations to perform:
  Apply all migrations: bnf
Running migrations:
  Applying bnf.0001_squashed_0002_20250425... OK
Importing bnf data...
2026-07-29T11:27:42.601251Z [info     ] Loading BNF type               [coding_systems.bnf.import_data] type=Chapter
2026-07-29T11:27:42.673715Z [info     ] Loading BNF type               [coding_systems.bnf.import_data] type=Section
2026-07-29T11:27:43.234549Z [info     ] Loading BNF type               [coding_systems.bnf.import_data] type=Paragraph
2026-07-29T11:27:44.285959Z [info     ] Loading BNF type               [coding_systems.bnf.import_data] type=Subparagraph
2026-07-29T11:27:45.594722Z [info     ] Loading BNF type               [coding_systems.bnf.import_data] type='Chemical Substance'
2026-07-29T11:27:52.766660Z [info     ] Loading BNF type               [coding_systems.bnf.import_data] type=Product
2026-07-29T11:29:55.178517Z [info     ] Loading BNF type               [coding_systems.bnf.import_data] type=Presentation
Found 348 versions compatible with previous release 'bnf_86-2024-09-02_20240902'.
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 348/348 [00:07<00:00, 44.31it/s]
348 checked; 69 identified as compatible

*** APP RESTART REQUIRED ***
Import complete; run `dokku ps:restart opencodelists` to restart the app

Post-import checks:
just manage shell

>>> from coding_systems.versioning.models import CodingSystemRelease
>>> 
>>> release = (
...     CodingSystemRelease.objects
...     .filter(coding_system="bnf")
...     .latest("valid_from")
... )
>>> print(release.release_name)
88 (2025-03-01)
>>> print(release.valid_from)
2025-03-01
>>> print(release.state)
ready
>>> print(release.database_alias)
bnf_88-2025-03-01_20250301

>>> for release in (
...     CodingSystemRelease.objects
...     .filter(coding_system="bnf")
...     .order_by("-valid_from")
... ):
...     print(
...         release.release_name,
...         release.valid_from,
...         release.state,
...         release.database_alias,
...     )
... 
88 (2025-03-01) 2025-03-01 ready bnf_88-2025-03-01_20250301
86 (2024-09-02) 2024-09-02 ready bnf_86-2024-09-02_20240902
86 (2024-05-02) 2024-05-02 ready bnf_86-2024-05-02_20240502
86 (2024-01-01) 2024-01-01 ready bnf_86-2024-01-01_20240101
84 (2023-11-01) 2023-11-01 ready bnf_84-2023-11-01_20231101
84 (2023-09-01) 2023-09-01 ready bnf_84-2023-09-01_20230901
84 (2023-05-02) 2023-05-02 ready bnf_84-2023-05-02_20230502
84 (2023-02-01) 2023-02-01 ready bnf_84-2023-02-01_20230201
82 (2022-11-01) 2022-11-01 ready bnf_82-2022-11-01_20221101
unknown 1900-01-01 ready bnf_unknown_19000101

Try and create a codelist in the browser and check its made with the newly imported BNF Coding system release:
Screenshot from 2026-07-29 12-38-37

We can cehck for a Latest compatible release for the MontyTest3 codelist, which is showing as the newly imported BNF Coding system release:
Screenshot from 2026-07-29 12-43-46

To note

@KatieB5 KatieB5 changed the title Update import_data.py to use the new ODP CSV format Enable importing of BNF data releases using the new ODP CSV format Jul 29, 2026

@Jongmassey Jongmassey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM 🚀

KatieB5 added 2 commits August 3, 2026 12:02
Previously, we imported BNF data from ZIP archives downloaded from the NHSBSA Information Services Portal (ISP).
The ISP is no longer available, and BNF releases are now published via the NHSBSA Open Data Portal (ODP).

The ODP provides BNF releases as CSV files rather than ZIP archives,
with an additional MONTH_YEAR column and updated column naming convention.

This change makes the minimum updates required to support importing the latest BNF releases from the ODP
while preserving the existing import workflow described in `coding_systems/bnf/README.md`.

Importer updates

- import BNF releases directly from CSV files
- normalise CSV headers to support the new ODP column naming convention
- remove ZIP extraction from the BNF import path

Test updates

- update the BNF import fixture to match the test CSV data to the new ODP CSV format
- update the import tests to use the new CSV fixture
@KatieB5
KatieB5 force-pushed the KatieB5/get-bnf-updates-from-odp-api branch from f681e12 to f6bee3f Compare August 3, 2026 11:46
@KatieB5
KatieB5 marked this pull request as ready for review August 3, 2026 11:56
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