Skip to content

Commit

Permalink
Merge cc70460 into 8e11980
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiamakaObitube authored Sep 1, 2019
2 parents 8e11980 + cc70460 commit 80d4229
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 10 deletions.
39 changes: 38 additions & 1 deletion src/controllers/RequestController.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class RequestController {
try {
const { id } = req.decoded;
const { body } = req;
const { dataValues } = await Request.create({ ...body, userId: id });
const { dataValues } = await Request.create({ ...body, UserId: id });
if (dataValues.id) {
HelperMethods.requestSuccessful(res, {
success: true,
Expand Down Expand Up @@ -66,6 +66,43 @@ class RequestController {
return HelperMethods.serverError(res);
}
}

/**
* Reject a Request
* Route: PATCH: /request
* @param {object} req - HTTP Request object
* @param {object} res - HTTP Response object
* @return {res} res - HTTP Response object
* @memberof RequestController
*/
static async rejectRequest(req, res) {
try {
const { role } = req.decoded;
const { id } = req.params;

if (role === 'Manager') {
const requestExist = await Request.findOne({
where: { id }
});

if (requestExist.status === 'OPEN') {
await requestExist.update({ status: 'REJECTED' });
return HelperMethods
.requestSuccessful(res, {
success: true,
message: 'Your request is rejected',
}, 200);
}
return HelperMethods.clientError(res, 'This request had already been rejected',
400);
}
return HelperMethods.clientError(res, 'You are not authorized to update this request',
400);
} catch (error) {
if (error.errors) return HelperMethods.sequelizeValidationError(res, error);
return HelperMethods.serverError(res);
}
}
}

export default RequestController;
7 changes: 6 additions & 1 deletion src/migrations/03-create-requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4
},
userId: {
UserId: {
type: Sequelize.UUID,
references: {
model: 'Users',
Expand Down Expand Up @@ -33,6 +33,11 @@ module.exports = {
values: ['BUSINESS', 'VACATION', 'EXPEDITION'],
defaultValue: 'BUSINESS'
},
status: {
type: Sequelize.ENUM,
values: ['OPEN', 'REJECTED', 'APPROVED'],
defaultValue: 'OPEN'
},
accommodationId: {
type: Sequelize.UUID,
references: {
Expand Down
7 changes: 6 additions & 1 deletion src/models/Request.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,17 @@ export default (sequelize, DataTypes) => {
type: DataTypes.ENUM,
values: ['BUSINESS', 'VACATION', 'EXPEDITION'],
defaultValue: 'BUSINESS'
},
status: {
type: DataTypes.ENUM,
values: ['OPEN', 'REJECTED', 'APPROVED'],
defaultValue: 'OPEN'
}
});

Request.associate = models => {
Request.belongsTo(models.User, {
foreignKey: 'userId',
foreignKey: 'UserId',
onDelete: 'CASCADE',
});
Request.belongsTo(models.Accommodation, {
Expand Down
4 changes: 2 additions & 2 deletions src/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ export default (sequelize, DataTypes) => {
{
classMethods: {
associate: models => {
User.hasMany(models.Requests, {
foreignKey: 'userId',
User.hasMany(models.Request, {
foreignKey: 'UserId',
as: 'users_request',
});
}
Expand Down
5 changes: 5 additions & 0 deletions src/routes/requestRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ const requestRoutes = app => {
Authorization.checkToken,
Validate.validateUserInput,
RequestController.bookAReturnTrip);

app.patch('/api/v1/request/reject/:id',
// Validate.validateUserInput,
Authorization.checkToken,
RequestController.rejectRequest);
};

export default requestRoutes;
12 changes: 8 additions & 4 deletions src/seeders/03-demo-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ module.exports = {
flightDate: '2019-06-21',
returnDate: '2019-03-21',
accommodationId: '2125be7b-f1f1-4f0a-af86-49c657870b5c',
userId: '3821b930-ce48-4ac8-9ddf-ee3bf7980d08',
UserId: '3821b930-ce48-4ac8-9ddf-ee3bf7980d08',
reason: 'VACATION',
status: 'OPEN',
createdAt: new Date(),
updatedAt: new Date()
},
Expand All @@ -19,8 +20,9 @@ module.exports = {
flightDate: '2019-06-21',
returnDate: '2019-03-21',
accommodationId: '9c41e609-7a30-4211-9d10-146a9c54ee74',
userId: '96dc6b6d-7a77-4322-8756-e22f181d952c',
UserId: '96dc6b6d-7a77-4322-8756-e22f181d952c',
reason: 'BUSINESS',
status: 'OPEN',
createdAt: new Date(),
updatedAt: new Date()
},
Expand All @@ -31,8 +33,9 @@ module.exports = {
flightDate: '2019-06-21',
returnDate: '2019-03-21',
accommodationId: '2125be7b-f1f1-4f0a-af86-49c657870b5c',
userId: '79ddfd3b-5c83-4beb-815e-55b1c95230e1',
UserId: '79ddfd3b-5c83-4beb-815e-55b1c95230e1',
reason: 'EXPEDITION',
status: 'OPEN',
createdAt: new Date(),
updatedAt: new Date()
},
Expand All @@ -43,8 +46,9 @@ module.exports = {
flightDate: '2019-06-21',
returnDate: '2019-03-21',
accommodationId: '35106536-deb5-4111-bd90-9ddfac5d348b',
userId: '4712fc7e-ca41-457f-872e-4a64b79efbba',
UserId: '4712fc7e-ca41-457f-872e-4a64b79efbba',
reason: 'BUSINESS',
status: 'OPEN',
createdAt: new Date(),
updatedAt: new Date()
},
Expand Down
32 changes: 31 additions & 1 deletion src/test/integrationTests/requestController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ describe('Integration tests for the request controller', () => {
accommodationId: '2125be7b-f1f1-4f0a-af86-49c657870b5c',
userId: '79ddfd3b-5c83-4beb-815e-55b1c95230e1',
reason: 'EXPEDITION',
status: 'OPEN'
};
let token;
before('login with an existing user details from the seeded data', async () => {
const response = await chai.request(app).post('/api/v1/auth/login')
.send({
email: 'demo1@demo.com',
email: 'demo3@demo.com',
password: 'password',
});
token = response.body.data.userDetails.token;
Expand Down Expand Up @@ -94,4 +95,33 @@ describe('Integration tests for the request controller', () => {
expect(response.body.success).to.equal(false);
});
});
describe('Test for a manager to reject trip request', () => {
it('should reject a trip', async () => {
const requestId = '8bda0fe3-a55a-4fd9-914d-9d93b53491b6';
const response = await chai
.request(app)
.patch(`/api/v1/request/reject/${requestId}`)
.set('x-access-token', token)
.send(tripDetails);
expect(response.status).to.equal(200);
expect(response.body.data).to.have.property('message');
expect(response.body.data.message).to.equal('Your request is rejected');
expect(response.body.data).to.have.property('success');
expect(response.body.data.success).to.equal(true);
});

it('should not reject an already rejected request', async () => {
const id = '8bda0fe3-a55a-4fd9-914d-9d93b53491b6';
const response = await chai
.request(app)
.patch(`/api/v1/request/reject/${id}`)
.set('x-access-token', token)
.send(tripDetails);
expect(response.status).to.equal(400);
expect(response.body).to.have.property('message');
expect(response.body.message).to.equal('This request had already been rejected');
expect(response.body).to.have.property('success');
expect(response.body.success).to.equal(false);
});
});
});
8 changes: 8 additions & 0 deletions src/test/unitTests/requestController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,12 @@ describe('unit test for the Request Controller', () => {
expect(response).to.have.property('success');
expect(response.success).to.equal(false);
});
it('should return a server error when an unexpected error happens', async () => {
stubbedMethod = sinon.stub(Request, 'create').throws({ dataValues: 'some thing' });
const response = await RequestController.rejectRequest(req, res);
expect(response).to.have.property('message');
expect(response.message).to.equal('Internal server error');
expect(response).to.have.property('success');
expect(response.success).to.equal(false);
});
});
45 changes: 45 additions & 0 deletions src/utils/ResponseHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* eslint-disable no-unused-vars */

/**
*
*
* @export
* @class ResponseHandler
*/
export default class ResponseHandler {
/**
*
*
* @static
* @param {*} res HTTP response object
* @param {*} data An object or array to send as a response
* @param {number} [status=200] HTTP response status code. Default is 200
* @memberof ResponseHandler
* @returns {void}
*/
static success(res, data, status = 200) {
return res.status(status).json({
success: true,
status,
data
});
}

/**
*
*
* @static
* @param {*} res HTTP response object
* @param {string} [message='Bad request'] An error message
* @param {number} [status=400] HTTP response status code. Default is 400
* @memberof ResponseHandler
* @returns {void}
*/
static error(res, message = 'Bad request', status = 400) {
return res.status(status).json({
success: false,
status,
error: message
});
}
}

0 comments on commit 80d4229

Please sign in to comment.