diff --git a/export_db.sh b/export_db.sh
index d7fa7c5..c02e464 100755
--- a/export_db.sh
+++ b/export_db.sh
@@ -1,4 +1,4 @@
#!/bin/bash
rm html/database.db
-sqlite3 database.db '.dump meta pbs_item pbs_mp pbs_mp_brand_name pbs_mpp pbs_item_restriction pbs_restriction pbs_restriction_criteria pbs_criteria pbs_criteria_parameter' | sqlite3 html/database.db
+sqlite3 database.db '.dump meta pbs_item pbs_mp mp_brand_name pbs_mpp pbs_item_restriction pbs_restriction pbs_restriction_criteria pbs_criteria pbs_criteria_parameter non_pbs_tpp' | sqlite3 html/database.db
diff --git a/find_pbs_brand_names.py b/find_brand_names.py
similarity index 58%
rename from find_pbs_brand_names.py
rename to find_brand_names.py
index b5242b2..4265e73 100755
--- a/find_pbs_brand_names.py
+++ b/find_brand_names.py
@@ -25,10 +25,11 @@ con.row_factory = sqlite3.Row
cur = con.cursor()
# Init schema
-cur.execute('DROP TABLE IF EXISTS pbs_mp_brand_name')
-cur.execute('CREATE TABLE pbs_mp_brand_name (id INTEGER PRIMARY KEY AUTOINCREMENT, mp_code STRING, brand_name STRING)')
+cur.execute('DROP TABLE IF EXISTS mp_brand_name')
+cur.execute('CREATE TABLE mp_brand_name (id INTEGER PRIMARY KEY AUTOINCREMENT, mp_preferred_term TEXT, brand_name TEXT)')
-cur.execute('SELECT * FROM pbs_tpp LEFT JOIN (SELECT code, mp_code FROM pbs_mpp) AS pbs_mpp ON pbs_tpp.mpp_code = pbs_mpp.code LEFT JOIN (SELECT code, preferred_term as mp_preferred_term FROM pbs_mp) AS pbs_mp ON pbs_mpp.mp_code = pbs_mp.code')
+# Get PBS brand names
+cur.execute('SELECT brand_name, mp_preferred_term FROM pbs_tpp LEFT JOIN (SELECT code, mp_code FROM pbs_mpp) AS pbs_mpp ON pbs_tpp.mpp_code = pbs_mpp.code LEFT JOIN (SELECT code, preferred_term as mp_preferred_term FROM pbs_mp) AS pbs_mp ON pbs_mpp.mp_code = pbs_mp.code')
brand_names = {}
for tpp in cur.fetchall():
@@ -53,21 +54,31 @@ for tpp in cur.fetchall():
# OK!
brand_name = ' '.join(words)
- if tpp['mp_code'] not in brand_names:
- brand_names[tpp['mp_code']] = set()
+ if tpp['mp_preferred_term'] not in brand_names:
+ brand_names[tpp['mp_preferred_term']] = set()
- brand_names[tpp['mp_code']].add(brand_name)
+ brand_names[tpp['mp_preferred_term']].add(brand_name)
+
+# Get non-PBS brand names
+cur.execute('SELECT * FROM non_pbs_tpp')
+for tpp in cur.fetchall():
+ # This is manually curated so no need for cleaning
+
+ if tpp['mp_preferred_term'] not in brand_names:
+ brand_names[tpp['mp_preferred_term']] = set()
+
+ brand_names[tpp['mp_preferred_term']].add(tpp['brand_name'])
# Reduce names with unambiguous prefixes
-for mp_code in sorted(brand_names.keys()):
- for brand_name in list(brand_names[mp_code]):
+for mp_preferred_term in sorted(brand_names.keys()):
+ for brand_name in list(brand_names[mp_preferred_term]):
# Can we reduce the length of the name?
words = brand_name.split()
for i in range(1, len(words)):
short_name = ' '.join(words[0:i])
- if any(b.startswith(short_name) for m in brand_names.keys() if m != mp_code for b in brand_names[m]):
+ if any(b.startswith(short_name) for m in brand_names.keys() if m != mp_preferred_term for b in brand_names[m]):
# Conflict
continue
@@ -76,14 +87,14 @@ for mp_code in sorted(brand_names.keys()):
continue
# Can shorten
- if brand_name in brand_names[mp_code]:
- brand_names[mp_code].remove(brand_name)
- brand_names[mp_code].add(short_name)
+ if brand_name in brand_names[mp_preferred_term]:
+ brand_names[mp_preferred_term].remove(brand_name)
+ brand_names[mp_preferred_term].add(short_name)
break
# Add to database
-for mp_code in sorted(brand_names.keys()):
- for brand_name in sorted(list(brand_names[mp_code])):
- cur.execute('INSERT INTO pbs_mp_brand_name (mp_code, brand_name) VALUES (?, ?)', (mp_code, brand_name))
+for mp_preferred_term in sorted(brand_names.keys()):
+ for brand_name in sorted(list(brand_names[mp_preferred_term])):
+ cur.execute('INSERT INTO mp_brand_name (mp_preferred_term, brand_name) VALUES (?, ?)', (mp_preferred_term, brand_name))
con.commit()
diff --git a/full_build_db.sh b/full_build_db.sh
index 47f5d9b..878cd58 100755
--- a/full_build_db.sh
+++ b/full_build_db.sh
@@ -2,5 +2,6 @@
./import_pbs_xml.py || exit 1
./render_pbs_criteria.py || exit 1
-./find_pbs_brand_names.py || exit 1
+./import_non_pbs.py || exit 1
+./find_brand_names.py || exit 1
./export_db.sh
diff --git a/html/index.html b/html/index.html
index 93f2a38..ded0dca 100644
--- a/html/index.html
+++ b/html/index.html
@@ -97,11 +97,11 @@
document.getElementById('pbs-date').innerText = {'01': 'January', '02': 'February', '03': 'March', '04': 'April', '05': 'May', '06': 'June', '07': 'July', '08': 'August', '09': 'September', '10': 'October', '11': 'November', '12': 'December'}[pbs_date_bits[1]] + ' ' + pbs_date_bits[0];
// Initialise search bar
- const mp_preferred_terms = execAsScalars(db.prepare('SELECT preferred_term FROM pbs_mp ORDER BY LOWER(preferred_term)'));
+ const mp_preferred_terms = execAsScalars(db.prepare('SELECT * FROM (SELECT preferred_term FROM pbs_mp UNION SELECT mp_preferred_term AS preferred_term FROM non_pbs_tpp) ORDER BY LOWER(preferred_term)'));
let data = mp_preferred_terms.map(mp_preferred_term => ({'label': mp_preferred_term, 'preview': mp_preferred_term, 'value': mp_preferred_term}));
- const tpp_brand_names = execAsObjects(db.prepare('SELECT * FROM pbs_mp_brand_name LEFT JOIN pbs_mp ON pbs_mp_brand_name.mp_code = pbs_mp.code ORDER BY LOWER(brand_name)'));
- data = data.concat(tpp_brand_names.map(tpp_brand_name => ({'label': tpp_brand_name['brand_name'], 'preview': tpp_brand_name['brand_name'] + ' (' + tpp_brand_name['preferred_term'] + ')', 'value': tpp_brand_name['preferred_term']})));
+ const tpp_brand_names = execAsObjects(db.prepare('SELECT * FROM mp_brand_name ORDER BY LOWER(brand_name)'));
+ data = data.concat(tpp_brand_names.map(tpp_brand_name => ({'label': tpp_brand_name['brand_name'], 'preview': tpp_brand_name['brand_name'] + ' (' + tpp_brand_name['mp_preferred_term'] + ')', 'value': tpp_brand_name['mp_preferred_term']})));
const autocomplete = new Autocomplete(document.getElementById('search-input'), {
data: data,
@@ -120,7 +120,15 @@
document.getElementById('search-input').value = item.value;
// Find matching PBS items
- let stmt = db.prepare('SELECT * FROM pbs_item LEFT JOIN (SELECT code AS mpp_code, preferred_term AS mpp_preferred_term, mp_code FROM pbs_mpp) AS pbs_mpp ON pbs_item.mpp_code = pbs_mpp.mpp_code LEFT JOIN (SELECT code AS mp_code, preferred_term AS mp_preferred_term FROM pbs_mp) AS pbs_mp ON pbs_mpp.mp_code = pbs_mp.mp_code WHERE LOWER(mp_preferred_term) = ?');
+ let stmt = db.prepare(
+ 'SELECT * FROM (' +
+ ' SELECT code, mp_preferred_term, mpp_preferred_term, benefit_type, maximum_prescribable_units, number_repeats, program FROM pbs_item' +
+ ' LEFT JOIN (SELECT code AS mpp_code, preferred_term AS mpp_preferred_term, mp_code FROM pbs_mpp) AS pbs_mpp ON pbs_item.mpp_code = pbs_mpp.mpp_code' +
+ ' LEFT JOIN (SELECT code AS mp_code, preferred_term AS mp_preferred_term FROM pbs_mp) AS pbs_mp ON pbs_mpp.mp_code = pbs_mp.mp_code' +
+ ' UNION SELECT DISTINCT NULL AS code, mp_preferred_term, mpp_preferred_term, "unrestricted" AS benefit_type, NULL AS maximum_prescribable_units, NULL AS number_repeats, "NA" AS program FROM non_pbs_tpp' +
+ ' )' +
+ ' WHERE LOWER(mp_preferred_term) = ?'
+ );
stmt.bind([item.value.toLowerCase()]);
const items = execAsObjects(stmt);
@@ -136,7 +144,11 @@
const restrictions = execAsObjects(stmt);
const tr = document.createElement('tr');
- let td = document.createElement('td'); td.innerHTML = '' + item['code'] + ''; tr.appendChild(td);
+ let td = document.createElement('td');
+ if (item['code']) {
+ td.innerHTML = '' + item['code'] + '';
+ }
+ tr.appendChild(td);
td = document.createElement('td');
let div = document.createElement('div'); div.innerText = item['mpp_preferred_term']; td.appendChild(div);
@@ -174,8 +186,17 @@
td = document.createElement('td'); td.innerText = item['maximum_prescribable_units']; tr.appendChild(td);
td = document.createElement('td'); td.innerText = item['number_repeats']; tr.appendChild(td);
- if (item['program'] === 'R1') {
- td = document.createElement('td'); td.innerHTML = 'RPBS'; tr.appendChild(td);
+ if (item['program'] !== 'GE') {
+ td = document.createElement('td');
+ if (item['program'] === 'R1') {
+ td.innerHTML = 'RPBS';
+ } else if (item['program'] === 'NA') {
+ td.innerHTML = 'Non-PBS';
+ } else {
+ alert('Unknown program: ' + item['program']);
+ throw 'Unknown program: ' + item['program'];
+ }
+ tr.appendChild(td);
tr.classList.add('table-secondary');
} else if (item['benefit_type'] === 'unrestricted') {
td = document.createElement('td'); tr.appendChild(td);
diff --git a/import_non_pbs.py b/import_non_pbs.py
new file mode 100755
index 0000000..d4742b9
--- /dev/null
+++ b/import_non_pbs.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+# Copyright © 2023 Lee Yingtong Li (RunasSudo)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import csv
+import sqlite3
+
+# Open database
+con = sqlite3.connect('database.db')
+cur = con.cursor()
+
+# Init schema
+cur.execute('DROP TABLE IF EXISTS non_pbs_tpp')
+cur.execute('CREATE TABLE non_pbs_tpp (mp_preferred_term TEXT, mpp_preferred_term TEXT, brand_name TEXT)')
+
+with open('non_pbs.csv', 'r', newline='') as f:
+ reader = csv.DictReader(f)
+
+ for tpp in reader:
+ if not tpp['Hide']:
+ cur.execute('INSERT INTO non_pbs_tpp (mp_preferred_term, mpp_preferred_term, brand_name) VALUES (?, ?, ?)', (tpp['MP'], tpp['MPP'], tpp['TPP']))
+
+con.commit()
diff --git a/non_pbs.csv b/non_pbs.csv
new file mode 100644
index 0000000..fe77a34
--- /dev/null
+++ b/non_pbs.csv
@@ -0,0 +1,27 @@
+MP,MPP,TPP,Source,Accessed,Hide
+colecalciferol,"colecalciferol 25 microgram (1000 units) tablet, 60",OsteVit-D One-A-Day,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=74470001_2,2023-02-24,
+colecalciferol,"colecalciferol 25 microgram (1000 units) tablet, 250",OsteVit-D One-A-Day,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=74470001_2,2023-02-24,Hide
+colecalciferol,"colecalciferol 25 microgram (1000 units) capsule, 60",Caltrate Vitamin D Daily,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=2930001_2,2023-02-24,
+colecalciferol,"colecalciferol 25 microgram (1000 units) capsule, 60",Ostelin,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=21920001_2,2023-02-24,
+colecalciferol,"colecalciferol 25 microgram (1000 units) capsule, 130",Ostelin,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=21920001_2,2023-02-24,Hide
+colecalciferol,"colecalciferol 25 microgram (1000 units) capsule, 250",Ostelin,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=21920001_2,2023-02-24,Hide
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 60",Caltrate Bone Health,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 100",Caltrate Bone Health,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,Hide
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 120",Caltrate Bone Health,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,Hide
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 60",Cal-600 + D,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 100",Cal-600 + D,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,Hide
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 60",Ostelin Calcium & Vitamin D3,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 130",Ostelin Calcium & Vitamin D3,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,Hide
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) tablet, 250",Ostelin Calcium & Vitamin D3,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,Hide
+calcium + colecalciferol,"calcium 600 mg + colecalciferol 12.5 microgram (500 units) chewable tablet, 60",Ostelin Calcium & Vitamin D3,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/endocrine-drugs/drugs-affecting-bone/other-drugs-affecting-bone/calcium,2023-02-24,Hide
+ferrous sulfate + folic acid,"ferrous sulfate 270 mg (iron 87.4 mg) + folic acid 300 microgram capsule, 30",Fefol,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=2850001_2,2023-02-24,
+ferrous sulfate + folic acid,"ferrous sulfate 270 mg (iron 87.4 mg) + folic acid 300 microgram capsule, 60",Fefol,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=2850001_2,2023-02-24,Hide
+ferrous fumarate + ascorbic acid,"ferrous fumarate 304 mg (iron 100 mg) + ascorbic acid 20 mg capsule, 30",Ferropods,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=135900001_2,2023-02-24,
+ferrous sulfate,"ferrous sulfate 325 mg (iron 105 mg) tablet, 30",Ferro-grad,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=2870001_2,2023-02-24,
+ferrous sulfate + ascorbic acid,"ferrous sulfate 325 mg (iron 105 mg) + ascorbic acid 500 mg tablet, 30",Ferro-grad C,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=48460001_2,2023-02-24,
+ferrous sulfate + folic acid,"ferrous sulfate 250 mg (iron 80 mg) + folic acid 300 microgram tablet, 30",Ferro-grad F,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=2900001_2,2023-02-24,
+iron polymaltose,"iron (as polymaltose) 100 mg tablet, 30",Maltofer,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=6800001_2,2023-02-24,
+sodium chloride,"sodium chloride 600 mg tablet, 100",Saltabs,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=130430001_2,2023-02-24,
+sodium chloride,"sodium chloride 600 mg tablet, 100",Toppin,https://www.mimsonline.com.au.acs.hcn.com.au/Search/AbbrPI.aspx?ID=21820001_2,2023-02-24,
+zinc sulfate,"zinc (as sulfate) 50 mg capsule, 100",Zincaps,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/blood-electrolytes/tables/oral-electrolytes-table,2023-02-24,
+tapentadol,"tapentadol 50 mg tablet, 20",Palexia IR,https://amhonline.amh.net.au.acs.hcn.com.au/chapters/analgesics/drugs-pain-relief/opioid-analgesics/tapentadol,2023-02-24,