1 | /*
|
2 |
|
3 | ----------------------------------------------------------------------------
|
4 | | qewd-ripple: QEWD-based Middle Tier for Ripple OSI |
|
5 | | |
|
6 | | Copyright (c) 2016-17 Ripple Foundation Community Interest Company |
|
7 | | All rights reserved. |
|
8 | | |
|
9 | | http://rippleosi.org |
|
10 | | Email: code.custodian@rippleosi.org |
|
11 | | |
|
12 | | Author: Rob Tweed, M/Gateway Developments Ltd |
|
13 | | |
|
14 | | Licensed under the Apache License, Version 2.0 (the "License"); |
|
15 | | you may not use this file except in compliance with the License. |
|
16 | | You may obtain a copy of the License at |
|
17 | | |
|
18 | | http://www.apache.org/licenses/LICENSE-2.0 |
|
19 | | |
|
20 | | Unless required by applicable law or agreed to in writing, software |
|
21 | | distributed under the License is distributed on an "AS IS" BASIS, |
|
22 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
23 | | See the License for the specific language governing permissions and |
|
24 | | limitations under the License. |
|
25 | ----------------------------------------------------------------------------
|
26 |
|
27 | 9 March 2017
|
28 |
|
29 | */
|
30 |
|
31 | /*
|
32 |
|
33 | Clinical Statement Storage
|
34 |
|
35 | Incoming POST payload
|
36 |
|
37 | {
|
38 | "type": "Clinical Note",
|
39 | "text": "Patient presented with shoulder pain.\r\nIf it doesn\'t improve, will need laparoscopic surgical exploration +/- repair",
|
40 | "author": "Dr John Smith",
|
41 |
|
42 | "contentStore": {
|
43 | // this allows return from the UI of the content store information
|
44 |
|
45 | "name": "ts", // need to know which content store was used
|
46 | "phrases": [
|
47 | // these are the content store phrase Ids used to create the text
|
48 |
|
49 | // the middle tier will obtain the full triplet data from the content store
|
50 |
|
51 | {id: 123, tag: 'ortho'},
|
52 | {id: 124, value: 10, tag: 'chestpain'} // this phrase had a variable value
|
53 | ]
|
54 | }
|
55 | }
|
56 |
|
57 |
|
58 | Stored as:
|
59 |
|
60 | clinicalStatements('byPatient', patientId, sourceId) =
|
61 |
|
62 | {
|
63 | "sourceId: 'xxxxxxxxx',
|
64 | "type": "Clinical Note",
|
65 | "text": "Patient presented with shoulder pain.\r\nIf it doesn\'t improve, will need laparoscopic surgical exploration +/- repair",
|
66 | "author": "Dr John Smith",
|
67 | "tags": {
|
68 | "ortho": true,
|
69 | "chestpain": true
|
70 | },
|
71 | dateCreated: 123456677,
|
72 | source: 'ethercis',
|
73 |
|
74 | "phrases": [
|
75 | { text: 'uiText',
|
76 | tag: 'ortho',
|
77 | subject: 'xxxxx',
|
78 | value: 'yyyy',
|
79 | unit: 'zzzz'
|
80 | },
|
81 | ]
|
82 | }
|
83 |
|
84 | */
|
85 |
|
86 |
|
87 | var uuid = require('uuid/v4');
|
88 | var contentStore = require('qewd-content-store');
|
89 | var createIndices = require('./createIndices');
|
90 |
|
91 | function postStatement(patientId, session, payload, finished) {
|
92 | console.log('postStatement - payload = ' + JSON.stringify(payload));
|
93 |
|
94 | if (!payload.type || payload.type === '') {
|
95 | return finished({error: 'Missing or empty Clinical Statement Type'});
|
96 | }
|
97 |
|
98 | if (!payload.text || payload.text === '') {
|
99 | return finished({error: 'Missing or empty text'});
|
100 | }
|
101 |
|
102 | if (!payload.author || payload.author === '') {
|
103 | return finished({error: 'Missing or empty author'});
|
104 | }
|
105 |
|
106 | if (!payload.contentStore) {
|
107 | return finished({error: 'Missing Content Store Details'});
|
108 | }
|
109 |
|
110 | if (!payload.contentStore.name || payload.contentStore.name === '') {
|
111 | return finished({error: 'Missing or empty Content Store Name'});
|
112 | }
|
113 |
|
114 | var content = contentStore.get.call(this, payload.contentStore.name);
|
115 |
|
116 | var phrases = [];
|
117 | var tags = {};
|
118 | if (payload.contentStore.phrases) {
|
119 | payload.contentStore.phrases.forEach(function(phraseObj) {
|
120 | if (phraseObj.id) {
|
121 | var phrase = content.get(phraseObj.id, '_all');
|
122 | var result = {
|
123 | text: phrase.uiPhrase,
|
124 | tag: phraseObj.tag,
|
125 | };
|
126 | tags[phraseObj.tag] = true;
|
127 | result.subject = phraseObj.subject || phrase.subject.value;
|
128 | var value;
|
129 | if (phraseObj.value) value = phraseObj.value;
|
130 | if (!value && phrase.value && phrase.value.value) value = phrase.value.value;
|
131 | if (value) result.value = value;
|
132 | var unit;
|
133 | if (phraseObj.unit) unit = phraseObj.unit;
|
134 | if (!unit && phrase.unit && phrase.unit.value) unit = phrase.unit.value;
|
135 | if (unit) result.unit = unit;
|
136 | phrases.push(result);
|
137 | }
|
138 | });
|
139 | }
|
140 |
|
141 |
|
142 | // OK the clinical statement can now be saved
|
143 |
|
144 | // create a sourceId uuid
|
145 |
|
146 | var sourceId = uuid();
|
147 |
|
148 | var clinicalStatement = {
|
149 | type: payload.type,
|
150 | text: payload.text,
|
151 | author: payload.author,
|
152 | sourceId: sourceId,
|
153 | source: 'ethercis',
|
154 | dateCreated: new Date().getTime(),
|
155 | tags: tags,
|
156 | phrases: phrases
|
157 | };
|
158 |
|
159 | var docName = this.userDefined.clinicalStatementsDocumentName;
|
160 | var clinicalDoc = new this.documentStore.DocumentNode(docName, ['byPatient', patientId, sourceId]);
|
161 | clinicalDoc.setDocument(clinicalStatement);
|
162 |
|
163 | // create subject, value and unit indices
|
164 |
|
165 | createIndices.forOneRecord.call(this, patientId, sourceId, clinicalStatement);
|
166 |
|
167 | session.data.$(['patients', patientId, 'clinicalStatements']).delete(); // force re-fetching of updated statements
|
168 |
|
169 | // temporary log to check what raw data is being sent
|
170 |
|
171 | var log = new this.documentStore.DocumentNode('CSLog');
|
172 | var index = log.$('index').increment();
|
173 | log.$(['payload', index]).setDocument(payload);
|
174 | log.$(['payload', index, 'sourceId']).value = sourceId;
|
175 |
|
176 | finished({sourceId: sourceId});
|
177 | }
|
178 |
|
179 |
|
180 | module.exports = postStatement;
|