-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #221 from bcgsc/release/v7.12.0
Release/v7.12.0
- Loading branch information
Showing
10 changed files
with
690 additions
and
253 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
const HTTP_STATUS = require('http-status-codes'); | ||
const express = require('express'); | ||
|
||
const router = express.Router({mergeParams: true}); | ||
|
||
const {Op, literal} = require('sequelize'); | ||
const db = require('../../models'); | ||
const logger = require('../../log'); | ||
|
||
const {KB_PIVOT_MAPPING} = require('../../constants'); | ||
|
||
const KBMATCHEXCLUDE = ['id', 'reportId', 'variantId', 'deletedAt', 'updatedBy']; | ||
const getVariants = async (tableName, variantType, reportId) => { | ||
return db.models[tableName].scope('extended').findAll({ | ||
order: [['id', 'ASC']], | ||
attributes: { | ||
include: [[literal(`'${variantType}'`), 'variantType']], | ||
}, | ||
where: { | ||
reportId, | ||
}, | ||
include: [ | ||
{ | ||
model: db.models.kbMatches, | ||
attributes: {exclude: KBMATCHEXCLUDE}, | ||
}, | ||
], | ||
}); | ||
}; | ||
|
||
const therapeuticAssociationFilter = { | ||
id: {[Op.ne]: null}, | ||
[Op.or]: [{iprEvidenceLevel: ['IPR-A', 'IPR-B']}], | ||
category: 'therapeutic', | ||
matchedCancer: true, | ||
variantType: {[Op.is]: literal('distinct from \'exp\'')}, | ||
}; | ||
|
||
// PSQL natively ignores null on equal checks. | ||
// Literal is used in order to accomodate NULL rows. | ||
const cancerRelevanceFilter = { | ||
id: {[Op.ne]: null}, | ||
[Op.not]: { | ||
[Op.or]: [ | ||
{iprEvidenceLevel: {[Op.is]: literal('not distinct from \'IPR-A\'')}}, | ||
{iprEvidenceLevel: {[Op.is]: literal('not distinct from \'IPR-B\'')}}, | ||
], | ||
category: 'therapeutic', | ||
matchedCancer: true, | ||
}, | ||
variantType: {[Op.is]: literal('distinct from \'exp\'')}, | ||
}; | ||
|
||
const unknownSignificanceIncludes = ['mut']; | ||
|
||
const unknownSignificanceGeneFilter = { | ||
[Op.or]: [{oncogene: true}, {tumourSuppressor: true}], | ||
}; | ||
|
||
const getRapidReportVariants = async (tableName, variantType, reportId, rapidTable) => { | ||
const therapeuticAssociationResults = await db.models[tableName].scope('extended').findAll({ | ||
order: [['id', 'ASC']], | ||
attributes: { | ||
include: [[literal(`'${variantType}'`), 'variantType']], | ||
}, | ||
where: { | ||
reportId, | ||
}, | ||
include: [ | ||
{ | ||
model: db.models.kbMatches, | ||
attributes: {exclude: KBMATCHEXCLUDE}, | ||
where: {...therapeuticAssociationFilter}, | ||
}, | ||
], | ||
}); | ||
|
||
if (rapidTable === 'therapeuticAssociation') { | ||
return therapeuticAssociationResults; | ||
} | ||
|
||
const cancerRelevanceResultsFiltered = []; | ||
const cancerRelevanceResults = await db.models[tableName].scope('extended').findAll({ | ||
order: [['id', 'ASC']], | ||
attributes: { | ||
include: [[literal(`'${variantType}'`), 'variantType']], | ||
}, | ||
where: { | ||
reportId, | ||
}, | ||
include: [ | ||
{ | ||
model: db.models.kbMatches, | ||
where: {...cancerRelevanceFilter}, | ||
attributes: {exclude: KBMATCHEXCLUDE}, | ||
}, | ||
], | ||
}); | ||
|
||
for (const row of cancerRelevanceResults) { | ||
if (!(therapeuticAssociationResults.find( | ||
(e) => {return e.ident === row.ident;}, | ||
))) { | ||
cancerRelevanceResultsFiltered.push(row); | ||
} | ||
} | ||
|
||
if (rapidTable === 'cancerRelevance') { | ||
return cancerRelevanceResultsFiltered; | ||
} | ||
|
||
const unknownSignificanceResultsFiltered = []; | ||
let unknownSignificanceResults = []; | ||
|
||
if (unknownSignificanceIncludes.includes(variantType)) { | ||
unknownSignificanceResults = await db.models[tableName].scope('extended').findAll({ | ||
order: [['id', 'ASC']], | ||
attributes: { | ||
include: [[literal(`'${variantType}'`), 'variantType']], | ||
}, | ||
where: { | ||
reportId, | ||
}, | ||
include: [ | ||
{ | ||
model: db.models.kbMatches, | ||
attributes: {exclude: KBMATCHEXCLUDE}, | ||
}, | ||
{ | ||
model: db.models.genes.scope('minimal'), | ||
as: 'gene', | ||
where: unknownSignificanceGeneFilter, | ||
}, | ||
], | ||
}); | ||
} | ||
|
||
for (const row of unknownSignificanceResults) { | ||
if (!(therapeuticAssociationResults.find( | ||
(e) => {return e.ident === row.ident;}, | ||
)) && !(cancerRelevanceResultsFiltered.find( | ||
(e) => {return e.ident === row.ident;}, | ||
))) { | ||
unknownSignificanceResultsFiltered.push(row); | ||
} | ||
} | ||
|
||
return unknownSignificanceResultsFiltered; | ||
}; | ||
|
||
// Routing for Alteration | ||
router.route('/') | ||
.get(async (req, res) => { | ||
// Get all variants for this report | ||
// Cache was removed from this endpoint due to requiring multiple tables, | ||
// increasing the chance of retrieving outdated data | ||
const {query: {rapidTable}} = req; | ||
|
||
try { | ||
const variantTypes = Object.keys(KB_PIVOT_MAPPING); | ||
const variantsArray = []; | ||
|
||
for (const variantType of variantTypes) { | ||
const tableName = KB_PIVOT_MAPPING[variantType]; | ||
|
||
if (rapidTable) { | ||
variantsArray.push(await getRapidReportVariants(tableName, variantType, req.report.id, rapidTable)); | ||
} else { | ||
variantsArray.push(await getVariants(tableName, variantType, req.report.id)); | ||
} | ||
} | ||
|
||
const results = variantsArray.flat(1); | ||
|
||
return res.json(results); | ||
} catch (error) { | ||
logger.error(`Unable to retrieve variants ${error}`); | ||
return res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ | ||
error: {message: 'Unable to retrieve variants'}, | ||
}); | ||
} | ||
}); | ||
|
||
module.exports = router; |
47 changes: 47 additions & 0 deletions
47
migrations/20221202195545-DEVSU-1891-add-columns-to-germline-report.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
const GSM_TABLE = 'germline_small_mutations_variant'; | ||
|
||
module.exports = { | ||
up: async (queryInterface, Sq) => { | ||
return queryInterface.sequelize.transaction(async (transaction) => { | ||
await queryInterface.addColumn( | ||
GSM_TABLE, | ||
'cgl_review_result', | ||
{type: Sq.ENUM(['pathogenic', 'likely pathogenic', 'VUS', 'likely benign', 'benign']), | ||
defaultValue: null}, | ||
{transaction}, | ||
); | ||
await queryInterface.addColumn( | ||
GSM_TABLE, | ||
'returned_to_clinician', | ||
{type: Sq.ENUM(['yes', 'no']), | ||
defaultValue: null}, | ||
{transaction}, | ||
); | ||
await queryInterface.addColumn( | ||
GSM_TABLE, | ||
'referral_hcp', | ||
{type: Sq.ENUM(['yes', 'no']), | ||
defaultValue: null}, | ||
{transaction}, | ||
); | ||
await queryInterface.addColumn( | ||
GSM_TABLE, | ||
'known_to_hcp', | ||
{type: Sq.ENUM(['yes', 'no']), | ||
defaultValue: null}, | ||
{transaction}, | ||
); | ||
await queryInterface.addColumn( | ||
GSM_TABLE, | ||
'reason_no_hcp_referral', | ||
{type: Sq.TEXT, | ||
defaultValue: null}, | ||
{transaction}, | ||
); | ||
}); | ||
}, | ||
|
||
down: async () => { | ||
throw new Error('Not Implemented!'); | ||
}, | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.