Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7,130 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oddb.org

Description

Open Drug Database for Switzerland. See the live version at http://ch.oddb.org

Features/Problems

  • SDIF Interactions: Drug interaction checking uses the SDIF (Swiss Drug Interactions Finder) SQLite database (data/sqlite/interactions.db). Four sources: EPha.ch curated ATC-to-ATC interactions, substance-level matches, ATC class-level keyword matching in Swissmedic FachInfo text, and CYP enzyme-mediated interactions. Each interaction shows its source (EPha.ch or Swissmedic FI) with type badge (Wirkstoff, ATC-Klasse, CYP). Route indicators (topisch, i.v., s.c., etc.) and approved combination therapy hints are displayed next to drug names. FI results display a "Gegenrichtung hat höhere Einstufung" hint when their severity is below the pair maximum across all interaction types. EPha results show the hint only for asymmetric EPha ratings between directions.
  • Twitter share and mail/notify icons have been removed from drug search result lists.
  • Some email-Addresses are still hardcoded. That needs to be fixed and placed into etc/oddb.yml
  • If you install oddb.org via gem please also see these instructions.

Requirements

  • git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
  • rbenv install 3.4.5
  • Linux: sudo apt-get install apache2 daemontools daemontools-run pkg-config libmagickwand-dev libpq-dev libmagickcore-dev graphicsmagick uuid-dev
  • macOS: brew install libpq graphicsmagick ossp-uuid (use bundle config build.pg --with-pg-config=$(brew --prefix libpq)/bin/pg_config for the pg gem)
  • bzcat 22:00-postgresql_database-ch_oddb-backup.bz2 | su -c psql -l postgres -p 5433 ch_odd
  • see Guide.txt

Useful commands

Reparse compositions of 5 digit Swissmedic Numbers (issue #139)

sudo -u apache bundle exec ruby jobs/import_swissmedic_only update_compositions 67685 60134

Reparse all compositions

sudo -u apache bundle exec ruby jobs/import_swissmedic_only update_compositions

Check all packages

sudo -u apache bundle exec ruby jobs/import_swissmedic_only check

Reparse FachInfo/PatInfo text for a specific IKSNR

bundle exec ruby jobs/update_textinfo_swissmedicinfo --skip --target=both 62822 --reparse

Note: The fiparse daemon (DRb on port 10002) runs as a separate process managed by daemontools (/etc/service/fiparse). After making code changes to ext/fiparse/src/, restart the daemon with sudo svc -h /etc/service/fiparse for changes to take effect.

Fachinfo Table Rendering

Tables from swissmedicinfo are parsed by detect_table? in ext/fiparse/src/textinfo_html_parser.rb. Tables with percentage-width styles are rendered as preformatted text; others are rendered as HTML tables with proper colspan/rowspan support. The view (src/view/chapter.rb) only emits colspan/rowspan attributes when > 1 to avoid invalid colspan="0" in the output.

Swiyu Login

The app uses Swiyu wallet-based authentication (OID4VP). After exceeding the 5-search query limit, users are prompted to log in. The login flow passes a return_url parameter so users are redirected back to their last search result after authentication.

BSV FHIR Import

The BSV SL (Spezialitätenliste) data is imported from FHIR NDJSON exports. As of June 2026, jobs/import_bsv uses the FHIR NDJSON source by default (mirroring oddb2xml); pass --no-fhir to fall back to the legacy XMLPublications.zip import. The dedicated jobs/import_bsv_fhir job remains as an explicit alias. The FHIR data follows the ch-epl Implementation Guide. As of the Feb 2026 IG update, productPrice and costShare are nested inside the reimbursementSL extension on RegulatedAuthorization resources. As of April 2026, the import downloads three per-language NDJSON files directly (foph-sl-export-latest-{de,fr,it}.ndjson) so French and Italian product names and limitation texts are populated alongside the German source. As of June 2026, change detection no longer re-downloads the ~93 MB files every run: a cheap HTTP HEAD reads each -latest- file's Last-Modified date, derives the immutable dated link (foph-sl-export-<YYYYMMDD>-<lang>.ndjson), and saves it in a <file>.source sidecar — the download and reparse are skipped entirely while the date is unchanged. As of July 2026, the SL-introduction / price-change flags that drive the med-drugs xls export (OuwerkerkPlugin, sent to just-medical) are computed correctly again: fix_flags_with_rss_logic_for now reads the previous price via pack.price_public(1) (the new price has already been stored at index 0 by the time it runs), mirroring the RSS feed logic. Previously it read the just-stored current price, so new Kassenzulässigkeiten (:sl_entry), price cuts and price rises were silently dropped from the export while sl_introduction.rss still listed them. As of August 2026 limitation texts are imported again: BAG no longer inlines them in a limitationText sub-extension but publishes them as separate ClinicalUseDefinition resources referenced via limitationIndication, so the importer now follows that reference. Without it every limitation was skipped and only 16 legacy texts remained in the database while the export carried some 6300. The referenced resource id is the LimitationCode (e.g. ABEVMY.07), which BAG confirms is limitation-specific and stable across publications; the FR/IT exports use the same ids with translated text. The BAG "IndC" code (indicationCode, e.g. 22064.07) is rendered as the subheading of the limitation text.

Med-Drugs XLS Export

The monthly med-drugs xls sent to just-medical (OuwerkerkPlugin) runs as a follower of jobs/import_bsv and combines registration-level change flags from the :swissmedic log group with package-level flags from :bsv_sl. As of August 2026 these change flags are merged into the month's existing log instead of overwriting it (Updater#merge_previous_change_flags, shared with the BSV path). Each import run only reports what changed since the previous download, so without the merge a second run in the same month wiped out what the first had recorded. That is exactly what happened in July 2026: Swissmedic published a corrupt "Zugelassene Packungen" file on 2026-07-04 (wrong Packungsgrösse on ~3200 packages) and republished it corrected on 2026-07-08; the later run compared the corrected file against the corrupt one, produced a :size-only mass diff and overwrote the 27 new registrations recorded by the earlier run. Since :size has no equivalent in OuwerkerkPlugin::NUMERIC_FLAGS, every Swissmedic row was then filtered out and the August export contained no new registrations. SwissmedicPlugin#warn_if_degenerate_diff additionally logs a SwissmedicDiff SUSPECT warning when a diff is dominated by a single flag, which is the signature of a corrupt file on one side of the comparison.

Refdata Partner API

Refdata migrated their platform on 2026-04-01. The Partner SOAP service (used for company and doctor imports) requires an API key. Set refdata_api_key in etc/oddb.yml (or the REFDATA_API_KEY env var). Register at developer.refdata.ch to obtain a key.

Drug Shortage Import

jobs/update_drugshortage imports current Swiss drug shortages from drugshortage.ch. In May 2026 the upstream site migrated from an ASP.NET HTML page to a WordPress + JSON API; the plugin fetches https://www.drugshortage.ch/api/api_engpaesse.php (the official "show all current shortages" endpoint, ~705 active records — endpoint moved under /api/ in June 2026) and parses gtin, mutation, status, lieferdatum, id per record. status values gained a leading category-number prefix ("1 aktuell keine Lieferungen"), which the plugin strips to keep shortage_state stable. shortage_link is built from the stable upstream id as https://www.drugshortage.ch/index.php/detail-lieferengpass/?ID=<id>. Cached fixture lives at data/json/drugshortage-latest.json. Later in June 2026 the API also began requiring HMAC-signed requests (otherwise HTTP 403 "Zugriff verweigert – fehlende Header"): each call sends X-Timestamp, X-Nonce, an X-Signature (HMAC-SHA256(secret, "<ts>|<nonce>|api_engpaesse") as hex) and X-Requested-With, generated per request by ShortagePlugin#shortage_source_headers.

Stale PostgreSQL Connections

If the app crashes with PQsocket() can't get socket descriptor, the ODBA connection pool holds dead database connections. A monkey-patch in src/util/odba_connection_patch.rb automatically detects stale connections and reconnects with up to 3 retries. This handles PostgreSQL restarts, idle timeouts, and other connection drops transparently.

Rebuild corrupted ODBA search indices

If searches fail with NoMethodError: undefined method 'fetch_ids', an ODBA index is corrupted. The app will show an error page with the index name. Rebuild it with: bundle exec ruby jobs/rebuild_indices <index_name>

For example: bundle exec ruby jobs/rebuild_indices sequence_index

Tests

  • to run the Tests you need to do

    • bundle install
    • bundle exec ruby test/suite.rb
    • bundle exec rspec spec/parslet_spec.rb # for parsing the compositions
    • look at the index.html in the coverage directory
  • There are some Selenium/Watir based GUI integration tests. For details on how to use them have a look at tests_watir.textile. By default they are run using the gem headless (this can be overrriden by setting the environment variable ODDB_NO_HEADLESS)

  • There is test/wrk_performance.lua allows a stress test with a typical load. See test/wrk_performance.lua for details on howto run it

Local Documentation

  • To build your local documentation do:
    • rdoc1.9 --op documentation

Install

  • sudo gem install oddb.org

Developers

French Translation Help

License

oddb.org

  • GPLv3.0

qrcode.js

  • doc/resources/javascript/qrcode.js — Licensed under the MIT license

Trademarks

The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED

Issues

For Issues please open one on Github.

Releases

Packages

Used by

Contributors

Languages