1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | var mySQL = require('./mySQL');
|
32 | var template = require('qewd-template');
|
33 | var dateTime = require('./dateTime');
|
34 |
|
35 | var count;
|
36 |
|
37 | function getDepartments(callback) {
|
38 | var deptsCache = new this.documentStore.DocumentNode('rippleMedicalDepts');
|
39 |
|
40 | var query = 'SELECT * FROM medical_departments';
|
41 | mySQL.query(query, function(depts) {
|
42 | if(depts.error) {
|
43 | callback(depts.error);
|
44 | return;
|
45 | }
|
46 | depts.forEach(function(dept) {
|
47 | deptsCache.$(dept.id).setDocument(dept);
|
48 | });
|
49 | if (callback) callback();
|
50 | });
|
51 | }
|
52 |
|
53 | function getGPs(callback) {
|
54 | var gpCache = new this.documentStore.DocumentNode('rippleGPs');
|
55 |
|
56 | var query = 'SELECT * FROM general_practitioners';
|
57 | mySQL.query(query, function(gps) {
|
58 | if(gps.error) {
|
59 | callback(gps.error);
|
60 | return;
|
61 | }
|
62 | gps.forEach(function(gp) {
|
63 | gpCache.$(gp.id).setDocument(gp);
|
64 | });
|
65 | if (callback) callback();
|
66 | });
|
67 | }
|
68 |
|
69 | function formatPatientData(row) {
|
70 |
|
71 | var gpCache = new this.documentStore.DocumentNode('rippleGPs');
|
72 | var deptCache = new this.documentStore.DocumentNode('rippleMedicalDepts');
|
73 | var gpData = gpCache.$(row.gp_id);
|
74 | var gp = gpData.getDocument();
|
75 |
|
76 | var patient = {};
|
77 | patient.id = row.nhs_number;
|
78 | patient.nhsNumber = row.nhs_number;
|
79 | patient.name = row.first_name + ' ' + row.last_name;
|
80 | patient.address = formatAddressData(row.address_1, row.address_2, row.address_3, row.address_4, row.address_5, row.postcode);
|
81 | patient.dateOfBirth = new Date(row.date_of_birth).getTime();
|
82 | patient.gender = row.gender || '';
|
83 | patient.phone = row.phone || '';
|
84 | patient.gpName = gp.gp_name || '';
|
85 | patient.gpAddress = formatAddressData(gp.address_1, gp.address_2, gp.address_3, gp.address_4, gp.address_5, gp.postcode);
|
86 | patient.pasNo = row.pas_number || '';
|
87 | patient.department = deptCache.$([row.department_id, 'department']).value;
|
88 |
|
89 | return patient;
|
90 | }
|
91 |
|
92 | function formatAddressData(address_1, address_2, address_3, address_4, address_5, postcode) {
|
93 | var address = '';
|
94 | var comma = ' ';
|
95 | if (address_1) {
|
96 | address = address_1;
|
97 | comma = ', ';
|
98 | }
|
99 | if (address_2) {
|
100 | address = address + comma + address_2;
|
101 | comma = ', ';
|
102 | }
|
103 | if (address_3) {
|
104 | address = address + comma + address_3;
|
105 | comma = ', ';
|
106 | }
|
107 | if (address_4) {
|
108 | address = address + comma + address_4;
|
109 | comma = ', ';
|
110 | }
|
111 | if (address_5) {
|
112 | address = address + comma + address_5;
|
113 | comma = ', ';
|
114 | }
|
115 | if (postcode) {
|
116 | address = address + comma + postcode;
|
117 | comma = ', ';
|
118 | }
|
119 |
|
120 | return address;
|
121 | }
|
122 |
|
123 | function runQuery(query, params, callback) {
|
124 | query = template.replace(query, params);
|
125 | console.log('** query: ' + query);
|
126 | var self = this;
|
127 |
|
128 | mySQL.query(query, function(rows) {
|
129 | if(rows.error) {
|
130 | if (callback) callback(rows);
|
131 | return;
|
132 | }
|
133 | var results = [];
|
134 | rows.forEach(function(row) {
|
135 | results.push(formatPatientData.call(self, row));
|
136 | });
|
137 | if (callback) callback(results);
|
138 | });
|
139 | }
|
140 |
|
141 | function addGenderToQuery(query, params) {
|
142 | if (!params.sexFemale && !params.sexMale) return query;
|
143 | var gender = 'male';
|
144 | if (params.sexFemale) gender = 'female';
|
145 | params.gender = gender;
|
146 | query = query + " AND lower(P.gender) = '{{gender}}'";
|
147 | return query;
|
148 | }
|
149 |
|
150 | function advancedSearch(params, callback) {
|
151 |
|
152 | var surname = params.surname;
|
153 | if (!surname || surname === '') {
|
154 | if (callback) callback ({error: 'Missing or invalid surname'});
|
155 | return;
|
156 | }
|
157 | var forename = params.forename;
|
158 | if (!forename || forename === '') {
|
159 | if (callback) callback ({error: 'Missing or invalid forename'});
|
160 | return;
|
161 | }
|
162 |
|
163 | params.surname = surname.toString().toLowerCase();
|
164 | params.forename = forename.toString().toLowerCase();
|
165 |
|
166 | var count = 0;
|
167 | for (var name in params) {
|
168 | count++;
|
169 | }
|
170 |
|
171 | var query = "SELECT * FROM patients P WHERE lower(P.last_name) = '{{surname}}' AND lower(P.first_name) LIKE '{{forename}}%'";
|
172 |
|
173 | if (count === 2) {
|
174 |
|
175 | return runQuery.call(this, query, params, callback);
|
176 | }
|
177 |
|
178 | if (params.dateOfBirth && params.dateOfBirth !== '') {
|
179 | params.dateOfBirth = dateTime.toSqlPASFormat(params.dateOfBirth);
|
180 | query = query + " AND P.date_of_birth = '{{dateOfBirth}}'";
|
181 | query = addGenderToQuery(query, params);
|
182 | return runQuery.call(this, query, params, callback);
|
183 | }
|
184 |
|
185 | if (params.rangeMin && params.rangeMax) {
|
186 | var now = new Date();
|
187 | var nowYear = now.getFullYear();
|
188 | var fromYear = nowYear - params.rangeMax;
|
189 | var rootDate = '-' + (now.getMonth() + 1) + '-' + now.getDate();
|
190 | var from = fromYear + rootDate;
|
191 | var toYear = nowYear - params.rangeMin;
|
192 | var to = toYear + rootDate;
|
193 | query = query + " AND P.date_of_birth >= '" + from + "' AND P.date_of_birth <= '" + to + "'";
|
194 | query = addGenderToQuery(query, params);
|
195 | return runQuery.call(this, query, params, callback);
|
196 | }
|
197 |
|
198 | query = addGenderToQuery(query, params);
|
199 | return runQuery.call(this, query, params, callback);
|
200 | }
|
201 |
|
202 | function searchByPatient(searchString, callback) {
|
203 |
|
204 | searchString = searchString.replace(/,/g , ' ');
|
205 |
|
206 | searchString = searchString.replace(/\s\s+/g, ' ');
|
207 |
|
208 | var pieces = searchString.split(' ');
|
209 |
|
210 | if (pieces.length === 0) {
|
211 | callback({error: 'Invalid search string'});
|
212 | return;
|
213 | }
|
214 |
|
215 | var firstName;
|
216 | var lastName;
|
217 | var nhsNumber;
|
218 | var dateOfBirth;
|
219 |
|
220 | if (pieces.length === 1) {
|
221 | lastName = pieces[0];
|
222 | firstName = '';
|
223 | if (Number.isInteger(parseInt(lastName))) {
|
224 | nhsNumber = lastName;
|
225 | lastName = '';
|
226 | firstName = '';
|
227 | dateOfBirth = '';
|
228 | }
|
229 | }
|
230 | else {
|
231 | firstName = pieces[0];
|
232 | lastName = pieces[1] || '';
|
233 | dateOfBirth = pieces[2] || '';
|
234 | }
|
235 |
|
236 | var query;
|
237 | if (nhsNumber) {
|
238 | query = 'SELECT * FROM patients P WHERE P.nhs_number = \'{{nhsNumber}}\'';
|
239 | }
|
240 |
|
241 | else {
|
242 | nhsNumber = '';
|
243 |
|
244 | if (lastName === '') {
|
245 | callback({error: 'Last Name not defined'});
|
246 | return;
|
247 | }
|
248 |
|
249 | query = 'SELECT * FROM patients P WHERE P.last_name LIKE \'{{lastName}}%\'';
|
250 | if (firstName && firstName !== '') {
|
251 | query = query + ' AND P.first_name LIKE \'{{firstName}}%\'';
|
252 | }
|
253 | if (dateOfBirth && dateOfBirth !== '') {
|
254 | query = query + ' AND P.date_of_birth = \'{{dateOfBirth}}\'';
|
255 | }
|
256 |
|
257 |
|
258 |
|
259 | }
|
260 |
|
261 | var params = {
|
262 | firstName: firstName,
|
263 | lastName: lastName,
|
264 | dateOfBirth: dateOfBirth,
|
265 | nhsNumber: nhsNumber
|
266 | };
|
267 |
|
268 | var q = this;
|
269 | query = template.replace(query, params);
|
270 |
|
271 | mySQL.query(query, function(rows) {
|
272 | if(rows.error) {
|
273 | if (callback) callback(rows);
|
274 | return;
|
275 | }
|
276 | var patientDetails = [];
|
277 | var noOfPatients = 0;
|
278 | rows.forEach(function(row) {
|
279 | noOfPatients++;
|
280 | var record = formatPatientData.call(q, row);
|
281 | var patient = {
|
282 | source: 'local',
|
283 | sourceId: record.id,
|
284 | name: record.name,
|
285 | address: record.address,
|
286 | dateOfBirth: record.dateOfBirth,
|
287 | gender: record.gender,
|
288 | nhsNumber: record.nhsNumber
|
289 | };
|
290 | patientDetails.push(patient);
|
291 | });
|
292 | var results = {
|
293 | totalPatients: noOfPatients,
|
294 | patientDetails: patientDetails
|
295 | };
|
296 | if (callback) callback(results);
|
297 | });
|
298 | }
|
299 |
|
300 | function getPatientDetails(nhsNumber, callback) {
|
301 |
|
302 | var q = this;
|
303 |
|
304 | var query = 'SELECT * FROM patients P WHERE P.nhs_number = ' + nhsNumber;
|
305 | mySQL.query(query, function(patients) {
|
306 | if(patients.error) {
|
307 | callback(patients);
|
308 | return;
|
309 | }
|
310 | var results = {};
|
311 | patients.forEach(function(row) {
|
312 | results[row.nhs_number] = formatPatientData.call(q, row);
|
313 | });
|
314 | if (callback) callback(results);
|
315 | });
|
316 |
|
317 | }
|
318 |
|
319 | function getOnePatient(nhsNumber, callback) {
|
320 |
|
321 | var q = this;
|
322 |
|
323 | var getOnePatientFn = function() {
|
324 | getPatientDetails.call(q, nhsNumber, callback);
|
325 | };
|
326 |
|
327 |
|
328 | count = 0;
|
329 | getDepartments.call(this, function(error) {
|
330 | if (error) {
|
331 | callback({error: error});
|
332 | return;
|
333 | }
|
334 | q.emit('mySQLResultsReady', getOnePatientFn);
|
335 | });
|
336 |
|
337 | getGPs.call(this, function(error) {
|
338 | if (error) {
|
339 | callback({error: error});
|
340 | return;
|
341 | }
|
342 | q.emit('mySQLResultsReady', getOnePatientFn);
|
343 | });
|
344 |
|
345 | }
|
346 |
|
347 | function getAllPatients(callback) {
|
348 |
|
349 | var q = this;
|
350 | var query = 'SELECT * FROM patients';
|
351 | mySQL.query(query, function(patients) {
|
352 | if(patients.error) {
|
353 | callback(patients);
|
354 | return;
|
355 | }
|
356 | var results = {};
|
357 | patients.forEach(function(row) {
|
358 | results[row.nhs_number] = formatPatientData.call(q, row);
|
359 | });
|
360 | if (callback) callback(results);
|
361 | });
|
362 | }
|
363 |
|
364 | function getPatients(callback) {
|
365 |
|
366 | var q = this;
|
367 |
|
368 | var getAllPatientsFn = function() {
|
369 | getAllPatients.call(q, callback);
|
370 | };
|
371 |
|
372 | count = 0;
|
373 | getDepartments.call(this, function(error) {
|
374 | if (error) {
|
375 | callback({error: error});
|
376 | return;
|
377 | }
|
378 | q.emit('mySQLResultsReady', getAllPatientsFn);
|
379 | });
|
380 |
|
381 | getGPs.call(this, function(error) {
|
382 | if (error) {
|
383 | callback({error: error});
|
384 | return;
|
385 | }
|
386 | q.emit('mySQLResultsReady', getAllPatientsFn);
|
387 | });
|
388 |
|
389 | }
|
390 |
|
391 | module.exports = {
|
392 | init: function() {
|
393 | var q = this;
|
394 |
|
395 | this.on('mySQLResultsReady', function(callback) {
|
396 | count++;
|
397 | console.log('mySQLResultsReady event - count = ' + count);
|
398 | if (count === 2) {
|
399 | if (callback) callback.call(q);
|
400 | return;
|
401 | }
|
402 | });
|
403 | },
|
404 | getPatients: getPatients,
|
405 | advancedSearch: advancedSearch,
|
406 | searchByPatient: searchByPatient,
|
407 | getOnePatient: getOnePatient
|
408 | };
|