Skip to content

Commit

Permalink
feat(db): implement db.convert() (#368)
Browse files Browse the repository at this point in the history
This commit implements `db.convert()` to convert hexadecimal strings on
objects into binary representation for insertion into the database.  It
is demonstrated on both the patient groups controller and enterprises
controller.

It is used as described here: #321 (comment)
```js
let data = req.body;

// do some logic

// convert the 'uuid' and 'debtor_uuid' properties to binary using
// db.bid()
data = db.convert(data, ['uuid', 'debtor_uuid']);

// now I can db.exec('INSERT...') or db.exec('UPDATE ...') easily.
It might help clean up the code a bit.
```
  • Loading branch information
jniles authored and sfount committed May 3, 2016
1 parent 68d8272 commit 8bccce7
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 82 deletions.
1 change: 0 additions & 1 deletion client/src/partials/enterprises/enterprises.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ function EnterpriseController(Enterprises, Currencies, StateFactory) {
vm.submit = submit;

function handler(error) {
console.error(error);
vm.state.error();
}

Expand Down
96 changes: 35 additions & 61 deletions server/controllers/admin/enterprises.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,24 @@
/**
* Enterprises Controller
*
* This controller is responsible for creating and updating Enterprises.
* Each Enterprise must necessarily have a name, an abbreviation, a geographical location as well as a currency
* And it is not possible to remove an Enterprise
*/
var db = require('../../lib/db');
var NotFound = require('../../lib/errors/NotFound');
* The Enterprises Controller
*
* This controller is responsible for creating and updating Enterprises.
* Each Enterprise must necessarily have a name, an abbreviation, a geographical location as well as a currency
* And it is not possible to remove an Enterprise
*/
const db = require('../../lib/db');
const NotFound = require('../../lib/errors/NotFound');

exports.lookupEnterprise = lookupEnterprise;

// converts uuids appropriately
function convert(data) {
if (data.location_id) {
data.location_id = db.bid(data.location_id);
}

return data;
}

// GET /enterprises
exports.list = function list(req, res, next) {
'use strict';
var sql;

sql = 'SELECT id, name, abbr FROM enterprise';
let sql = 'SELECT id, name, abbr FROM enterprise';

if (req.query.detailed === '1'){
sql =
'SELECT id, name, abbr, email, po_box, phone, BUID(location_id) as location_id, logo, currency_id FROM enterprise;';
'SELECT id, name, abbr, email, po_box, phone, BUID(location_id) AS location_id, logo, currency_id FROM enterprise;';
}

db.exec(sql)
Expand All @@ -43,54 +33,43 @@ exports.list = function list(req, res, next) {
// GET /enterprises/:id
exports.detail = function detail(req, res, next) {
'use strict';
var enterpriseId = req.params.id;

let enterpriseId = req.params.id;
lookupEnterprise(enterpriseId)
.then(function (enterprise) {
.then(function (enterprise) {
res.status(200).json(enterprise);
})
.catch(next)
.done();
};

function lookupEnterprise(id) {
var sql =
`SELECT id, name, abbr, email, po_box, phone, location_id, logo, currency_id
FROM enterprise WHERE id = ?`;

function lookupEnterprise(id) {
'use strict';

let sql =
`SELECT id, name, abbr, email, po_box, phone,
BUID(location_id) AS location_id, logo, currency_id
FROM enterprise WHERE id = ?;`;

return db.exec(sql, [id])
.then(function (rows) {
var enterprise;

if (!rows.length) {
throw new NotFound(`Could not find an Enterprise with id ${enterpriseId}`);
throw new NotFound(`Could not find an enterprise with id ${id}`);
}
enterprise = rows[0];
return enterprise;

return rows[0];
});
}


// POST /enterprises
exports.create = function create(req, res, next) {
'use strict';
var enterprise = convert(req.body.enterprise),
writeEnterpriseQuery;

if (!enterprise.name && !enterprise.abbr && !enterprise.location_id && !enterprise.currency_id ) {
res.status(400).json({
code : 'ERR_INVALID_REQUEST',
reason : 'A valid Enterprise must be have name, abbrevation, location and Currency '
});
return;
}

writeEnterpriseQuery = 'INSERT INTO enterprise (name, abbr, phone, email, location_id, logo, currency_id, po_box) VALUES (?);';
let enterprise = db.convert(req.body.enterprise, ['location_id']);
let sql =
'INSERT INTO enterprise SET ?;';

db.exec(writeEnterpriseQuery, [[
enterprise.name, enterprise.abbr, enterprise.phone, enterprise.email,
enterprise.location_id, enterprise.logo, enterprise.currency_id, enterprise.po_box
]])
db.exec(sql, [ enterprise ])
.then(function (row) {
res.status(201).json({ id : row.insertId });
})
Expand All @@ -101,26 +80,21 @@ exports.create = function create(req, res, next) {
// PUT /enterprises/:id
exports.update = function update(req, res, next) {
'use strict';
var sql;
var enterpriseId = req.params.id;
var queryData = convert(req.body);

delete queryData.id;
let sql = 'UPDATE enterprise SET ? WHERE id = ?;';
let data = db.convert(req.body, ['location_id']);
delete data.id;

sql = 'UPDATE enterprise SET ? WHERE id = ?;';

db.exec(sql, [queryData, enterpriseId])
db.exec(sql, [data, req.params.id])
.then(function (row) {
if (!row.affectedRows) {
throw new NotFound(`Could not find an Enterprise with id ${enterpriseId}`);
throw new NotFound(`Could not find an enterprise with id ${req.params.id}`);
}

var sql2 = 'SELECT id, name, abbr, phone, email, location_id, logo, currency_id, po_box FROM enterprise WHERE id = ?;';

return db.exec(sql2, [enterpriseId]);
return lookupEnterprise(req.params.id);
})
.then(function (rows) {
res.status(200).json(rows[0]);
.then(function (enterprise) {
res.status(200).json(enterprise);
})
.catch(next)
.done();
Expand Down
29 changes: 9 additions & 20 deletions server/controllers/medical/patientGroups.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
/**
* The /patient_groups HTTP API endpoint
*
* @module medical/patient_groups
* @module medical/patientGroups
*
* @description This controller is responsible for implementing all crud and others custom request
* on the patient groups table through the `/patient_groups` endpoint.
*
* @requires lib/db
* @requires node_uuid
**/

var db = require('../../lib/db');
var uuid = require('node-uuid');
var NotFound = require('../../lib/errors/NotFound');

// converts data's uuids to binary uuids as required
function convert(data) {
var keys = [ 'price_list_uuid' ];

keys.forEach(function (key) {
if (data[key]) {
data[key] = db.bid(data[key]);
}
});
* @requires lib/errors/NotFOund
*/

return data;
}
const db = require('../../lib/db');
const uuid = require('node-uuid');
const NotFound = require('../../lib/errors/NotFound');

/**
* Returns an array of patient groups
Expand Down Expand Up @@ -58,7 +46,7 @@ function list(req, res, next) {
function create(req, res, next) {
'use strict';

var record = convert(req.body);
let record = db.convert(req.body, ['price_list_uuid']);

// provide UUID if the client has not specified
record.uuid = db.bid(record.uuid || uuid.v4());
Expand All @@ -82,7 +70,7 @@ function update(req, res, next) {
var uid = db.bid(req.params.uuid);
var sql = 'UPDATE patient_group SET ? WHERE uuid = ?';

var data = convert(req.body);
var data = db.convert(req.body, ['price_list_uuid']);

if (data.created_at) {
data.created_at = new Date(data.created_at);
Expand Down Expand Up @@ -110,6 +98,7 @@ function update(req, res, next) {
* Remove a patient group in the database
*/
function remove(req, res, next) {
'use strict';
const id = db.bid(req.params.uuid);
var sql = 'DELETE FROM patient_group WHERE uuid = ?';

Expand Down
31 changes: 31 additions & 0 deletions server/lib/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,41 @@ function bid(hexUuid) {
return new Buffer(uuid.parse(hexUuid));
}

/**
* Converts values on the data object to binary uuids if they exist. If not, it
* will gracefully skip the key.
*
* @method convert
* @param {Object} data - an object with uuids to convert to binary
* @param {Array} keys - an array of keys on the data object, specifying which
* fields to convert
* @returns {Object} data - the data object, now converted
*
*/
function convert(data, keys) {
'use strict';

// clone the object
let clone = JSON.parse(JSON.stringify(data));

// loop through each key
keys.forEach(function (key) {

// the key exists on the object and value is a string
if (clone[key] && typeof clone[key] === 'string') {
clone[key] = bid(clone[key]);
}
});

return clone;
}


module.exports = {
initialise: initialise,
exec: exec,
transaction: transaction,
escape: sanitize,
convert: convert,
bid: bid
};

0 comments on commit 8bccce7

Please sign in to comment.