Skip to content

Commit

Permalink
feat(vouchers): implement delete server-side
Browse files Browse the repository at this point in the history
This commit implements the DELETE /transactions/:uuid route for the
vouchers route.

Closes #2161.
  • Loading branch information
jniles committed Oct 13, 2017
1 parent 00a1367 commit 2c3322d
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 30 deletions.
3 changes: 2 additions & 1 deletion server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
* @license GPL-2.0
* @copyright IMA World Health 2016
*/
// json2xls haldles an error in strict mode so we require it before

// json2xls handles an error in strict mode so we require it before
const json2xls = require('json2xls');

require('use-strict');
Expand Down
49 changes: 44 additions & 5 deletions server/controllers/finance/vouchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ exports.create = create;

exports.find = find;
exports.lookupVoucher = lookupVoucher;
exports.safelyDeleteVoucher = safelyDeleteVoucher;

/**
* GET /vouchers
Expand Down Expand Up @@ -165,7 +166,7 @@ function find(options) {
*/
function create(req, res, next) {
// alias both the voucher and the voucher items
const voucher = req.body.voucher;
const { voucher } = req.body;
let items = req.body.voucher.items || [];

// a voucher without two items doesn't make any sense in double-entry
Expand All @@ -174,8 +175,7 @@ function create(req, res, next) {
if (items.length < 2) {
next(
new BadRequest(
`Expected there to be at least two items, but only received
${items.length} items.`
`Expected there to be at least two items, but only received ${items.length} items.`
)
);

Expand Down Expand Up @@ -212,7 +212,8 @@ function create(req, res, next) {
});

// map items into an array of arrays
items = _.map(items,
items = _.map(
items,
util.take('uuid', 'account_id', 'debit', 'credit', 'voucher_uuid', 'document_uuid', 'entity_uuid')
);

Expand All @@ -224,11 +225,49 @@ function create(req, res, next) {
.addQuery('INSERT INTO voucher SET ?', [voucher])
.addQuery(
'INSERT INTO voucher_item (uuid, account_id, debit, credit, voucher_uuid, document_uuid, entity_uuid) VALUES ?',
[items])
[items]
)
.addQuery('CALL PostVoucher(?);', [voucher.uuid]);

transaction.execute()
.then(() => res.status(201).json({ uuid : vuid }))
.catch(next)
.done();
}


/**
* @function safelyDeleteVoucher
*
* @description
* This function deletes a voucher from the system. It assumes that
* checks have already been made for referencing transactions.
*/
function safelyDeleteVoucher(guid) {
const DELETE_TRANSACTION = `
DELETE FROM posting_journal WHERE record_uuid = ?;
`;

const DELETE_VOUCHER = `
DELETE FROM voucher WHERE uuid = ?;
`;

const DELETE_TRANSACTION_HISTORY = `
DELETE FROM transaction_history WHERE record_uuid = ?;
`;

const DELETE_DOCUMENT_MAP = `
DELETE FROM document_map WHERE uuid = ?;
`;

const binaryUuid = db.bid(guid);
const transaction = db.transaction();

transaction
.addQuery(DELETE_TRANSACTION, binaryUuid)
.addQuery(DELETE_TRANSACTION_HISTORY, binaryUuid)
.addQuery(DELETE_VOUCHER, binaryUuid)
.addQuery(DELETE_DOCUMENT_MAP, binaryUuid);

return transaction.execute();
}
1 change: 0 additions & 1 deletion test/integration/cash.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ describe('(/cash) Cash Payments', () => {
.catch(helpers.handler);
});

// attempt to delete a cash payment
it('DELETE /transactions/:uuid deletes a cash payment', () => {
return agent.delete(`/transactions/${TO_DELETE_UUID}`)
.then(res => {
Expand Down
61 changes: 38 additions & 23 deletions test/integration/vouchers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global expect, chai, agent */
/* global expect, agent */

const helpers = require('./helpers');
const uuid = require('node-uuid');
Expand All @@ -8,12 +8,14 @@ const uuid = require('node-uuid');
*
* This test suit is about the vouchers table
*/
describe('(/vouchers) The vouchers HTTP endpoint', function () {
describe('(/vouchers) The vouchers HTTP endpoint', () => {
const date = new Date();

const vUuid = 'b140c144-6ca8-47b0-99ba-94732cf6efde';
const numVouchers = 9;

const TO_DELETE_UUID = '3688e9ce-85ea-4b5c-9144-688177edcb63';

// balanced transaction with two lines (USD)
const voucher = {
date,
Expand All @@ -40,10 +42,10 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {

// NOTE: this voucher does not have any uuids
const items = [
{ account_id: 3631, debit: 11, credit: 0, document_uuid: uuid.v4(), entity_uuid: uuid.v4() },
{ account_id: 3637, debit: 0, credit: 11, document_uuid: uuid.v4(), entity_uuid: uuid.v4() },
{ account_id: 3631, debit: 0, credit: 12 },
{ account_id: 3628, debit: 12, credit: 0 },
{ account_id : 3631, debit : 11, credit : 0, document_uuid : uuid.v4(), entity_uuid : uuid.v4() },
{ account_id : 3637, debit : 0, credit : 11, document_uuid : uuid.v4(), entity_uuid : uuid.v4() },
{ account_id : 3631, debit : 0, credit : 12 },
{ account_id : 3628, debit : 12, credit : 0 },
];

const secondVoucher = {
Expand Down Expand Up @@ -96,7 +98,7 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {

let mockVoucher;

it('POST /vouchers create a new voucher record in voucher and voucher_item tables', function () {
it('POST /vouchers create a new voucher record in voucher and voucher_item tables', () => {
return agent.post('/vouchers')
.send({ voucher })
.then((res) => {
Expand All @@ -106,16 +108,16 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
.catch(helpers.handler);
});

it('POST /vouchers create a new voucher record with multiple voucher_items', function () {
it('POST /vouchers create a new voucher record with multiple voucher_items', () => {
return agent.post('/vouchers')
.send({ voucher: secondVoucher })
.send({ voucher : secondVoucher })
.then((res) => {
helpers.api.created(res);
})
.catch(helpers.handler);
});

it('POST /vouchers doesn\'t register when missing data', function () {
it('POST /vouchers doesn\'t register when missing data', () => {
const uid = uuid.v4();
mockVoucher = {
date,
Expand All @@ -142,14 +144,14 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
.catch(helpers.handler);
});

it('POST /vouchers will reject a voucher will less than two records', function () {
it('POST /vouchers will reject a voucher will less than two records', () => {
// attempt 1 - missing items completely + bad voucher
return agent.post('/vouchers')
.send({ voucher: { uuid: uuid.v4() } })
.then((res) => {
helpers.api.errored(res, 400);

// attempt 2 - only a single item
// attempt 2 - only a single item
return agent.post('/vouchers')
.send({ voucher: badVoucher });
})
Expand All @@ -159,25 +161,25 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
.catch(helpers.handler);
});

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

it('GET /vouchers?detailed=1 returns a list of vouchers', function () {
it('GET /vouchers?detailed=1 returns a list of vouchers', () => {
return agent.get('/vouchers?detailed=1')
.then((res) => {
helpers.api.listed(res, numVouchers);
})
.catch(helpers.handler);
});

it('GET /vouchers/:uuid returns a detail of a specified vouchers', function () {
it('GET /vouchers/:uuid returns a detail of a specified vouchers', () => {
return agent.get(`/vouchers/${voucher.uuid}`)
.then((res) => {
expect(res).to.have.status(200);
Expand All @@ -188,15 +190,15 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
.catch(helpers.handler);
});

it('GET /vouchers/:uuid returns a NOT FOUND (404) when unknown {uuid}', function () {
it('GET /vouchers/:uuid returns a NOT FOUND (404) when unknown {uuid}', () => {
return agent.get('/vouchers/unknown')
.then((res) => {
helpers.api.errored(res, 404);
})
.catch(helpers.handler);
});

it('GET /vouchers returns a list of vouchers specified by query string', function () {
it('GET /vouchers returns a list of vouchers specified by query string', () => {
return agent.get('/vouchers/?reference=unknown&detailed=1')
.then((res) => {
helpers.api.listed(res, 0);
Expand All @@ -211,4 +213,17 @@ describe('(/vouchers) The vouchers HTTP endpoint', function () {
})
.catch(helpers.handler);
});


it('DELETE /transactions/:uuid deletes a voucher', () => {
return agent.delete(`/transactions/${TO_DELETE_UUID}`)
.then(res => {
expect(res).to.have.status(201);
return agent.get(`/vouchers/${TO_DELETE_UUID}`);
})
.then(res => {
helpers.api.errored(res, 404);
})
.catch(helpers.handler);
});
});

0 comments on commit 2c3322d

Please sign in to comment.