Skip to content

Commit

Permalink
feat: add integration tests for edge cases.
Browse files Browse the repository at this point in the history
This commit tests and edge case where the journal voucher will not have
a fiscal year, an error state thrown in the database and reformatted in
JavaScript.  It shows that the posting process does proper error
handling.

I've also cleaned up the comments for documentation purposes.

Closes #313.
  • Loading branch information
jniles committed Apr 15, 2016
1 parent 4b4e771 commit d9a939f
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 21 deletions.
70 changes: 66 additions & 4 deletions server/controllers/finance/journal/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,24 @@
*
* This core module of the posting journal sets the posting session for
* modules that will be posting data to the posting journal.
*
*
*
*/

'use strict';

const q = require('q');
const BadRequest = require('../../../lib/errors/BadRequest');

/**
* Set up the SQL transaction with default variables useful for posting records
* to the posting journal.
* to the posting journal. In the final query, it checks that no values are
* corrupt before passing the transaction back for the copying query.
*
* If a value is missing/NULL, the stored procedure PostingJournalErrorHandler()
* will SIGNAL an error, terminating the transaction. This is expected to be
* handled using the handler() function below.
*
* @param {object} transaction - the transaction object
* @returns {object} transaction - the same transaction, with added queries
*
* NOTE - this expects SQL variables "@date" and "@enterpriseId" to be set.
*/
Expand Down Expand Up @@ -92,3 +98,59 @@ exports.setup = function setup(transaction) {

return transaction;
};

/**
* Core Error Handler
*
* This function will catch database errors generated during the posting
* transaction, and properly convert them into JavaScript errors to be
* sent to the client.
*
* @param {Error} error - the error object thrown by MySQL.
* @returns {Promise} handled - a rejected promise with converted error.
*/
exports.handler = function handler(error) {
let handled;

switch (error.sqlState) {
case '45001':
handled = new BadRequest(
'No enterprise found in the database.',
'ERRORS.NO_ENTERPRISE'
);
break;

case '45002':
handled = new BadRequest(
'No project found in the database.',
'ERRORS.NO_PROJECT'
);
break;

case '45003':
handled = new BadRequest(
'No fiscal year found in the database for the provided date.',
'ERRORS.NO_FISCAL_YEAR'
);
break;

case '45004':
handled = new BadRequest(
'No period found in the database for the provided date.',
'ERRORS.NO_FISCAL_YEAR'
);
break;

case '45005':
handled = new BadRequest(
'No exchange rate found in the database for the provided date.',
'ERRORS.NO_EXCHANGE_RATE'
);
break;

default:
handled = error;
}

return q.reject(handled);
};
19 changes: 9 additions & 10 deletions server/controllers/finance/journal/voucher.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
/**
*
*
*/

'use strict';

const core = require('./core');
const q = require('q');

/**
* This function is responsible for posting new records from the `voucher` table
* into the posting journal. It expects to be passed a transaction object and
* the (binary) uuid of the voucher to be posted.
*
* Using the core.js file, it initiates checks to make sure that the data is
* valid before posting. If any invalid data is found, MySQL signals an error,
* ending the transaction, and clearing all temporary variables.
*
* @param {object} transaction - the transaction query object
* @param {object} uuid - the binary voucher uuid being posted to the journal
*
* This function posts data from the `voucher` table to the posting journal.
*/
module.exports = function post(transaction, uuid) {

Expand Down Expand Up @@ -71,8 +73,5 @@ module.exports = function post(transaction, uuid) {
);

return transaction.execute()
.catch(function (error) {
/** @todo - custom error handling based on SQLSTATE */
return q.reject(error);
});
.catch(core.handler);
};
10 changes: 5 additions & 5 deletions server/models/procedures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ CREATE PROCEDURE PostingJournalErrorHandler(
BEGIN

-- set up error declarations
DECLARE NoEnterprise CONDITION FOR SQLSTATE '45000';
DECLARE NoProject CONDITION FOR SQLSTATE '45000';
DECLARE NoFiscalYear CONDITION FOR SQLSTATE '45000';
DECLARE NoPeriod CONDITION FOR SQLSTATE '45000';
DECLARE NoExchangeRate CONDITION FOR SQLSTATE '45000';
DECLARE NoEnterprise CONDITION FOR SQLSTATE '45001';
DECLARE NoProject CONDITION FOR SQLSTATE '45002';
DECLARE NoFiscalYear CONDITION FOR SQLSTATE '45003';
DECLARE NoPeriod CONDITION FOR SQLSTATE '45004';
DECLARE NoExchangeRate CONDITION FOR SQLSTATE '45005';

IF enterprise IS NULL THEN
SIGNAL NoEnterprise
Expand Down
36 changes: 34 additions & 2 deletions server/test/api/vouchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const uuid = require('node-uuid');
/**
* The /vouchers API endpoint
*
* @desc This test suit is about the vouchers table
* This test suit is about the vouchers table
*/
describe('(/vouchers) The vouchers HTTP endpoint', function () {
'use strict';
Expand Down Expand Up @@ -73,7 +73,7 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
uuid : uuid.v4(),
date : date,
project_id : 1,
currency_id : 1,
currency_id : helpers.data.USD,
amount : 10,
description : 'Voucher Transaction',
items : [{
Expand All @@ -84,6 +84,28 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
}]
};

// this voucher will not have an exchange rate
var predatedVoucher = {
uuid : uuid.v4(),
date : new Date('2000-01-01'),
project_id : 1,
currency_id : helpers.data.FC,
amount : 10,
description : 'Voucher Transaction',
user_id : 1,
items : [{
uuid : uuid.v4(),
account_id : 3627,
debit : 10,
credit : 0,
}, {
uuid : uuid.v4(),
account_id : 3637,
debit : 0,
credit : 10,
}]
};

var mockVoucher;

it('POST /vouchers create a new voucher record in voucher and voucher_item tables', function () {
Expand Down Expand Up @@ -149,6 +171,16 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
.catch(helpers.handler);
});

it('POST /vouchers will reject a voucher with an invalid exchange rate', function () {
return agent.post('/vouchers')
.send({ voucher : predatedVoucher })
.then(function (res) {
helpers.api.errored(res, 400);
expect(res.body.code).to.equal('ERRORS.NO_FISCAL_YEAR');
})
.catch(helpers.handler);
});

it('GET /vouchers returns a list of vouchers', function () {
return agent.get('/vouchers')
.then(function (res) {
Expand Down

0 comments on commit d9a939f

Please sign in to comment.