-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mCSD Changes plus more #122
base: master
Are you sure you want to change the base?
Changes from 14 commits
7f384c4
79719e0
8d94675
e2fdfde
40abee8
d30861f
cf47157
e02244d
c780475
57c94af
0b77116
bceb357
bad33b1
9f6ec56
fd18fe1
e7917ad
4aec672
01b9be6
f2f7caa
a1b0372
a53b317
1ec565b
1f7b149
e132c3d
6638aeb
c5c8eb3
cf86abb
cd29894
6c513b8
ee4b8bf
df9a54f
075e13f
7765333
2a9a8d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -360,9 +360,16 @@ module.exports = exports = (mongo) => { | |
if (entry._mpi) { | ||
search = entry._mpi.search | ||
} | ||
if ( entry._request.method == 'POST' ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check indentation |
||
entry._request.url = entry.resourceType | ||
} else { | ||
entry._request.url = entry.resourceType+"/"+entry.id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update variable to be defined in an template Literal way, making it easier to read |
||
} | ||
|
||
const ret = { | ||
fullUrl: `${config.getConf('server:publicFhirBase')}/${entry.resourceType}/${entry.id}`, | ||
resource: entry | ||
fullUrl: `${config.getConf('server:publicFhirBase')}/${entry.resourceType}/${entry.id}/_history/${entry.meta.versionId}`, | ||
resource: entry, | ||
request: entry._request | ||
} | ||
|
||
if (search) { | ||
|
@@ -543,7 +550,7 @@ module.exports = exports = (mongo) => { | |
*/ | ||
getPagingParams: (queryParams, callback) => { | ||
let _getpagesoffset = 0 | ||
let _count = 10 | ||
let _count = 100 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revert this to the default of 10. It can always be overridden by the client. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to be reverted to the default of 10, A query parameter (_count) can be sent to increase the paging count, If this is set to _count=0 then all results will be returned |
||
|
||
if (queryParams._getpagesoffset) { | ||
_getpagesoffset = parseInt(queryParams._getpagesoffset) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,12 +7,14 @@ | |
*/ | ||
'use strict' | ||
|
||
const moment = require('moment') | ||
const logger = require('winston') | ||
|
||
const FhirCommon = require('./common') | ||
const Authorization = require('../security/authorization') | ||
const Hooks = require('./hooks') | ||
const matchingConfig = require('../../config/matching') | ||
const QueryUtils = require('./query-utils'); | ||
|
||
const handleErrorAndBadRequest = (err, badRequest, callback) => { | ||
if (err) { | ||
|
@@ -30,6 +32,7 @@ const handleErrorAndBadRequest = (err, badRequest, callback) => { | |
module.exports = (mongo, modules) => { | ||
const fhirCommon = FhirCommon(mongo) | ||
const authorization = Authorization(mongo) | ||
const queryUtils = QueryUtils(mongo) | ||
const hooks = Hooks() | ||
|
||
return { | ||
|
@@ -321,6 +324,133 @@ module.exports = (mongo, modules) => { | |
}) | ||
}, | ||
|
||
/** | ||
* History for a resource. The 'query' field must be specified in the RequestContext parameter. | ||
* | ||
* @param {RequestContext} ctx | ||
* @param {String} resourceType The type of FHIR resource | ||
* @param {CoreCallback} callback | ||
*/ | ||
history: (ctx, resourceType, callback) => { | ||
authorization.authorize('history', ctx, resourceType, (err, badRequest) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
|
||
const fhirModule = modules[resourceType] | ||
hooks.executeBeforeHooks('history', fhirModule, ctx, resourceType, (err, badRequest) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
|
||
mongo.getDB((err, db) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
/* This doesn't work for deletes but saving in case needed later. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove commented out code |
||
let query = [ { $lookup : { from : resourceType+'_history', localField: "id", foreignField: "id", as: 'history' } }, | ||
{ $lookup : { from: resourceType, localField: 'id', foreignField: 'id', as : 'top' } }, | ||
{ $project : { allHist :{ $setUnion : ["$top","$history"] } } }, | ||
{ $unwind : "$allHist" }, | ||
{$replaceRoot: {newRoot:"$allHist"}} ] | ||
*/ | ||
let query = [ | ||
{ $limit: 1 }, | ||
{ $lookup: { from: resourceType, pipeline:[], as: "top" } }, | ||
{ $lookup: { from: resourceType+"_history", pipeline: [], as: "history" } }, | ||
{ $project: { all: { $setUnion: [ "$top", "$history" ] } } }, | ||
{ $unwind: "$all" }, | ||
{ $replaceRoot: { newRoot: "$all" } } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps another way to do this would be to just to two separate queries and combine the results? Might be more efficient. Although this way seems fine to until we actually see a performance issue. |
||
] | ||
|
||
if ( ctx.query._since ) { | ||
const matchClause = {$match: queryUtils.dateToMongoClause('meta.lastUpdated', 'ge'+ctx.query._since) } | ||
query[1].$lookup.pipeline.push( matchClause ) | ||
query[2].$lookup.pipeline.push( matchClause ) | ||
} | ||
|
||
let cntQuery = query.slice(0,query.length) | ||
cntQuery.push( {$count: 'total'} ) | ||
|
||
query.push( {$sort: {'meta.lastUpdated':-1} } ) | ||
|
||
|
||
mongo.util.debugLog(resourceType, 'history', query) | ||
|
||
fhirCommon.getPagingParams(ctx.query, (err, badRequest, _getpagesoffset, _count) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
|
||
const c = db.collection(resourceType) | ||
c.aggregate(cntQuery, (err, total) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
if ( total.length == 0 ) { | ||
const response = fhirCommon.bundleResults('history', [], 0, ctx.url) | ||
hooks.executeAfterHooks('history', fhirModule, ctx, resourceType, response, (err, badRequest, results) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
|
||
// format the updated entry array for the response | ||
if (results && results.entry) { | ||
results.entry.forEach((resource) => { | ||
fhirCommon.formatResource(resource.resource) | ||
}) | ||
} | ||
|
||
callback(null, { httpStatus: 200, resource: results }) | ||
}) | ||
} else { | ||
total = total[0].total | ||
|
||
|
||
c.aggregate(query).skip(_getpagesoffset).limit(_count).toArray((err, results) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
|
||
const response = fhirCommon.bundleResults('history', results, total, ctx.url) | ||
if (_getpagesoffset + _count < total) { | ||
fhirCommon.addBundleLinkNext(response, ctx.url, _getpagesoffset + _count, _count) | ||
} | ||
|
||
hooks.executeAfterHooks('history', fhirModule, ctx, resourceType, response, (err, badRequest, results) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
|
||
// format the updated entry array for the response | ||
if (results && results.entry) { | ||
results.entry.forEach((resource) => { | ||
fhirCommon.formatResource(resource.resource) | ||
}) | ||
} | ||
|
||
callback(null, { httpStatus: 200, resource: results }) | ||
}) | ||
|
||
|
||
})// find | ||
|
||
} | ||
|
||
|
||
}) | ||
}) | ||
|
||
|
||
}) //mongo.getdb. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove commented code |
||
}) | ||
}) | ||
}, | ||
|
||
|
||
|
||
/** | ||
* Create a new resource. | ||
* | ||
|
@@ -342,10 +472,13 @@ module.exports = (mongo, modules) => { | |
} | ||
|
||
const fhirModule = modules[resourceType] | ||
hooks.executeBeforeHooks('create', fhirModule, ctx, resourceType, resource, (err, badRequest) => { | ||
hooks.executeBeforeHooks('create', fhirModule, ctx, resourceType, resource, (err, badRequest, newResource) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
if ( newResource ) { | ||
resource = newResource; | ||
} | ||
|
||
if (!resource.resourceType || resource.resourceType !== resourceType) { | ||
return callback(null, fhirCommon.buildHTTPOutcome(400, 'error', 'invalid', 'Invalid resource type')) | ||
|
@@ -406,10 +539,13 @@ module.exports = (mongo, modules) => { | |
} | ||
|
||
const fhirModule = modules[resourceType] | ||
hooks.executeBeforeHooks('update', fhirModule, ctx, resourceType, resource, (err, badRequest) => { | ||
hooks.executeBeforeHooks('update', fhirModule, ctx, resourceType, resource, (err, badRequest, newResource) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
if ( newResource ) { | ||
resource = newResource; | ||
} | ||
if (!resource.resourceType || resource.resourceType !== resourceType) { | ||
return callback(null, fhirCommon.buildHTTPOutcome(400, 'error', 'invalid', 'Invalid resource type')) | ||
} | ||
|
@@ -430,7 +566,7 @@ module.exports = (mongo, modules) => { | |
resource.meta.versionId = fhirCommon.util.generateID() | ||
|
||
const options = { | ||
upsert: false, // TODO OHIE-168 | ||
upsert: true, // TODO OHIE-168 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should make this configurable via a config option with a default of |
||
returnOriginal: true | ||
} | ||
|
||
|
@@ -441,16 +577,6 @@ module.exports = (mongo, modules) => { | |
} | ||
|
||
if (!result.value) { | ||
return callback(null, fhirCommon.buildHTTPOutcome(404, 'information', 'not-found', 'Not found')) | ||
} | ||
|
||
delete result.value._id | ||
|
||
const cHistory = db.collection(`${resourceType}_history`) | ||
cHistory.insert(result.value, (err) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
hooks.executeAfterHooks('update', fhirModule, ctx, resourceType, resource, (err, badRequest) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
|
@@ -459,7 +585,26 @@ module.exports = (mongo, modules) => { | |
const location = `/fhir/${resourceType}/${id}/_history/${resource.meta.versionId}` | ||
callback(null, { httpStatus: 200, location: location, id: id }) | ||
}) | ||
}) | ||
//return callback(null, fhirCommon.buildHTTPOutcome(404, 'information', 'not-found', 'Not found')) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't we still need this instead of the callback at line 586? |
||
} else { | ||
|
||
delete result.value._id | ||
|
||
const cHistory = db.collection(`${resourceType}_history`) | ||
cHistory.insert(result.value, (err) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
hooks.executeAfterHooks('update', fhirModule, ctx, resourceType, resource, (err, badRequest) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
|
||
const location = `/fhir/${resourceType}/${id}/_history/${resource.meta.versionId}` | ||
callback(null, { httpStatus: 200, location: location, id: id }) | ||
}) | ||
}) | ||
} | ||
}) | ||
}) | ||
}) | ||
|
@@ -510,13 +655,33 @@ module.exports = (mongo, modules) => { | |
if (err) { | ||
return callback(err) | ||
} | ||
hooks.executeAfterHooks('delete', fhirModule, ctx, resourceType, historyDoc, (err, badRequest) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
|
||
// Also need to add a deleted record to the history. | ||
const dateFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZ' | ||
const deleteDoc = { | ||
id: historyDoc.id, | ||
resourceType: historyDoc.resourceType, | ||
_request: { method: "DELETE" }, | ||
meta: { lastUpdated: moment().format(dateFormat) } | ||
} | ||
|
||
cHistory.insert(deleteDoc, (err) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
callback(null, { httpStatus: 204, id: id }) | ||
hooks.executeAfterHooks('delete', fhirModule, ctx, resourceType, historyDoc, (err, badRequest) => { | ||
if (err || badRequest) { | ||
return handleErrorAndBadRequest(err, badRequest, callback) | ||
} | ||
|
||
callback(null, { httpStatus: 204, id: id }) | ||
}) | ||
|
||
}) | ||
|
||
|
||
|
||
}) | ||
} else { | ||
cHistory.remove({ id: id }, (err) => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: we should always use triple equals
===