feat: Currencies CRUD.

This commit is contained in:
Ahmed Bouhuolia
2020-04-19 18:26:22 +02:00
parent 090c744f57
commit 8c8ec1534e
5 changed files with 321 additions and 13 deletions

View File

@@ -243,6 +243,13 @@ factory.define('option', 'options', async () => {
};
});
factory.define('currency', 'currencies', async () => {
return {
currency_name: faker.lorem.slug(),
currency_code: 'USD',
};
});
factory.define('budget', 'budgets', async () => {
return {
name: faker.lorem.slug(),

View File

@@ -0,0 +1,12 @@
exports.up = function(knex) {
return knex.schema.createTable('currencies', table => {
table.increments();
table.string('currency_name');
table.string('currency_code', 4);
})
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('currencies');
};

View File

@@ -1,45 +1,136 @@
import express from 'express';
import { check, validationResult } from 'express-validator';
import { check, param, validationResult } from 'express-validator';
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
import Currency from '@/models/Currency';
import jwtAuth from '@/http/middleware/jwtAuth';
export default {
router() {
const router = express.Router();
router.use(jwtAuth);
router.get('/all',
router.get('/',
this.all.validation,
asyncMiddleware(this.all.handler));
router.get('/registered',
this.registered.validation,
asyncMiddleware(this.registered.handler));
router.post('/',
this.newCurrency.validation,
asyncMiddleware(this.newCurrency.handler));
router.post('/:id',
this.editCurrency.validation,
asyncMiddleware(this.editCurrency.handler));
router.delete('/:currency_code',
this.deleteCurrecy.validation,
asyncMiddleware(this.deleteCurrecy.handler));
return router;
},
/**
* Retrieve all registered currency details.
*/
all: {
validation: [],
async handler(req, res) {
const currencies = await Currency.query();
return res.status(200).send({
currencies: [
{ currency_code: 'USD', currency_sign: '$' },
{ currency_code: 'LYD', currency_sign: '' },
...currencies,
],
});
},
},
registered: {
validation: [],
newCurrency: {
validation: [
check('currency_name').exists().trim().escape(),
check('currency_code').exists().trim().escape(),
],
async handler(req, res) {
const validationErrors = validationResult(req);
if (!validationErrors.isEmpty()) {
return res.boom.badData(null, {
code: 'validation_error', ...validationErrors,
});
}
const form = { ...req.body };
const foundCurrency = await Currency.query()
.where('currency_code', form.currency_code);
if (foundCurrency.length > 0) {
return res.status(400).send({
errors: [{ type: 'CURRENCY.CODE.ALREADY.EXISTS', code: 100 }],
});
}
await Currency.query()
.insert({ ...form });
return res.status(200).send({
currencies: [
{ currency_code: 'USD', currency_sign: '$' },
{ currency_code: 'LYD', currency_sign: '' },
],
currency: { ...form },
});
},
},
deleteCurrecy: {
validation: [
param('currency_code').exists().trim().escape(),
],
async handler(req, res) {
const validationErrors = validationResult(req);
if (!validationErrors.isEmpty()) {
return res.boom.badData(null, {
code: 'validation_error', ...validationErrors,
});
}
const { currency_code: currencyCode } = req.params;
await Currency.query()
.where('currency_code', currencyCode)
.delete();
return res.status(200).send({ currency_code: currencyCode });
},
},
editCurrency: {
validation: [
param('id').exists().isNumeric().toInt(),
check('currency_name').exists().trim().escape(),
check('currency_code').exists().trim().escape(),
],
async handler(req, res) {
const validationErrors = validationResult(req);
if (!validationErrors.isEmpty()) {
return res.boom.badData(null, {
code: 'validation_error', ...validationErrors,
});
}
const form = { ...req.body };
const { id } = req.params;
const foundCurrency = await Currency.query()
.where('currency_code', form.currency_code)
.whereNot('id', id);
if (foundCurrency.length > 0) {
return res.status(400).send({
errors: [{ type: 'CURRENCY.CODE.ALREADY.EXISTS', code: 100 }],
});
}
await Currency.query()
.where('id', id)
.update({ ...form });
return res.status(200).send({
currency: { ...form },
});
},
},

View File

@@ -0,0 +1,10 @@
import BaseModel from '@/models/Model';
export default class Currency extends BaseModel {
/**
* Table name
*/
static get tableName() {
return 'currencies';
}
}

View File

@@ -0,0 +1,188 @@
import {
request,
create,
expect,
login,
} from '~/testInit';
import Currency from '@/models/Currency';
let loginRes;
describe('route: /currencies/', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST: `/api/currencies`', () => {
it('Should response unauthorized in case user was not logged in.', async () => {
const res = await request()
.post('/api/currencies')
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
});
it('Should `currency_name` be required.', async () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'currency_name', location: 'body',
});
});
it('Should `currency_code` be required.', async () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'currency_code', location: 'body',
});
});
it('Should response currency code is duplicated.', async () => {
create('currency', { currency_code: 'USD' });
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.send({
currency_code: 'USD',
currency_name: 'Dollar',
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'CURRENCY.CODE.ALREADY.EXISTS', code: 100,
});
});
it('Should insert currency details to the storage.', async () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.send({
currency_code: 'USD',
currency_name: 'Dollar',
});
const foundCurrency = await Currency.query().where('currency_code', 'USD');
expect(foundCurrency.length).equals(1);
expect(foundCurrency[0].currencyCode).equals('USD');
expect(foundCurrency[0].currencyName).equals('Dollar');
});
it('Should response success with correct data.', async () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.send({
currency_code: 'USD',
currency_name: 'Dollar',
});
expect(res.status).equals(200);
});
});
describe('DELETE: `/api/currencies/:currency_code`', () => {
it('Should delete the given currency code from the storage.', async () => {
const currency = await create('currency');
const res = await request()
.delete(`/api/currencies/${currency.currencyCode}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(200);
const foundCurrency = await Currency.query().where('currency_code', 'USD');
expect(foundCurrency.length).equals(0);
});
});
describe('POST: `/api/currencies/:id`', () => {
it('Should `currency_name` be required.', async () => {
const currency = await create('currency');
const res = await request()
.post(`/api/currencies/${currency.code}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'currency_name', location: 'body',
});
});
it('Should `currency_code` be required.', async () => {
const currency = await create('currency');
const res = await request()
.post(`/api/currencies/${currency.code}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'currency_code', location: 'body',
});
});
it('Should response currency code is duplicated.', async () => {
const currency1 = await create('currency');
const currency2 = await create('currency');
const res = await request()
.post(`/api/currencies/${currency2.id}`)
.set('x-access-token', loginRes.body.token)
.send({
currency_code: currency1.currencyCode,
currency_name: 'Dollar',
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'CURRENCY.CODE.ALREADY.EXISTS', code: 100,
});
});
it('Should update currency details of the given currency on the storage.', async () => {
const currency1 = await create('currency');
const currency2 = await create('currency');
const res = await request()
.post(`/api/currencies/${currency2.id}`)
.set('x-access-token', loginRes.body.token)
.send({
currency_code: 'ABC',
currency_name: 'Name',
});
const foundCurrency = await Currency.query().where('currency_code', 'ABC');
expect(foundCurrency.length).equals(1);
expect(foundCurrency[0].currencyCode).equals('ABC');
expect(foundCurrency[0].currencyName).equals('Name');
});
it('Should response success with correct data.', () => {
});
})
});