Skip to content

Commit

Permalink
ft(avail request for approval): Add feature that avails requests made…
Browse files Browse the repository at this point in the history
… by users to the manager they report to

- Add get requests route
- Add validations
- Add tests
[Finishes #169258643]
  • Loading branch information
nziokaivy committed Dec 2, 2019
1 parent 45feb9c commit 92529f1
Show file tree
Hide file tree
Showing 21 changed files with 343 additions and 101 deletions.
26 changes: 25 additions & 1 deletion src/controllers/TripController.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import ControllerHelper from '../helpers/ControllerHelper';
import emailHelper from '../helpers/EmailHelper';
import TripService from '../services/TripService';

const { availtripRequestsToManager } = TripService;

/**
* @export
* @class TripController
Expand Down Expand Up @@ -109,6 +111,28 @@ class TripController {
return Customize.errorMessage(req, res, err.message, 500);
}
}
}

/**
* Manager should be able to view requests for approvals
* @static
* @param {object} req request object
* @param {object} res response object
* @memberof TripController
* @returns {object} data
* @description PATCH api/v1/trips/requests
*/
static async getRequestsByManager(req, res) {
const { id } = req.user;

try {
const result = await availtripRequestsToManager(id);
if (result.length === 0) {
return Customize.errorMessage(req, res, 'No trip requests are available for review', 404);
}
return Customize.successMessage(req, res, 'Requests fetched successfully', result, 200);
} catch (error) {
return Customize.errorMessage(req, res, 'Oops! internal server error', 500);
}
}
}
export default TripController;
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ module.exports = {
type: Sequelize.STRING
},
managerId: {
type: Sequelize.INTEGER
type: Sequelize.INTEGER,
},
bio: {
type: Sequelize.STRING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = {
onUpdate: 'CASCADE',
defaultValue: 1 ,
},

createdAt: {
allowNull: false,
type: Sequelize.DATE
Expand Down
2 changes: 1 addition & 1 deletion src/database/models/tripRequests.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module.exports = (sequelize, DataTypes) => {
{onUpdate: 'cascade'});
tripRequests.hasMany(
models.trips,
{foreignKey: 'id'},
{targetKey: 'tripRequestId'},
{ onDelete: 'cascade'},
{onUpdate: 'cascade'});
};
Expand Down
7 changes: 6 additions & 1 deletion src/database/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ module.exports = (sequelize, DataTypes) => {
}, {});
users.associate = function(models) {
users.hasMany(models.tripRequests,
{foreignKey: 'id'},
{targetKey: 'userId'},
{ onDelete: 'cascade'},
{onUpdate: 'cascade'}
);
users.hasOne(models.userProfile,
{foreignKey: 'id'},
{ onDelete: 'cascade'},
{onUpdate: 'cascade'}
);
};
return users;
};
15 changes: 14 additions & 1 deletion src/database/seeders/20191114145912-users.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {
lastName: 'Doe',
email: 'demo@gmail.com',
password: '$2b$10$Q9H0gYzslg.oIvqoiWBEfesJoe.HTQT0Ezg5itN/h0a5Mf9gxWWvq',
roleId: 3,
roleId: 6,
isVerified: true,
signupType:'default',
createdAt: new Date(),
Expand All @@ -21,6 +21,7 @@ module.exports = {
password: '$2b$10$EVp9ow6OlwEldRIaXTdOB.sqG3zqyMUnOzNuAvaiVqzk6OvPcmSDC',
signupType: 'Barefoot',
isVerified: true,
roleId: 3,
createdAt: new Date(),
updatedAt: new Date()
},
Expand All @@ -30,6 +31,18 @@ module.exports = {
email: 'mytest@myemail.com',
password: '$2b$10$EVp9ow6OlwEldRIaXTdOB.sqG3zqyMUnOzNuAvaiVqzk6OvPcmSDC',
signupType: 'Barefoot',
roleId: 3,
isVerified: true,
createdAt: new Date(),
updatedAt: new Date()
},
{
firstName: 'Mary',
lastName: 'Doe',
email: 'marydoe@gmail.com',
password: 'Merry@12345',
signupType: 'Barefoot',
roleId: 3,
isVerified: true,
createdAt: new Date(),
updatedAt: new Date()
Expand Down
2 changes: 1 addition & 1 deletion src/database/seeders/20191114145913-user-profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
address: null,
imageURL:null,
department: null,
managerId: null,
managerId: 5,
bio: null,
createdAt: new Date(),
updatedAt: new Date()
Expand Down
3 changes: 2 additions & 1 deletion src/helpers/ControllerHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ class ControllerHelper {
const newTrip = await tripRequests.create({
userId, statusId: 1, tripTypeId
});
await tripRequests.findOne({ where: { userId } });
itinerary.forEach(async (item) => {
await trips.create({
tripRequestId: newTrip.dataValues.id,
originId: item.originId,
destinationId: item.destinationId,
reason: item.reason,
startDate: item.startDate,
returnDate: item.returnDate
returnDate: item.returnDate,
});
});
emailHelper.approveEmailHelper(req, process.env.MANAGER_EMAIL);
Expand Down
26 changes: 23 additions & 3 deletions src/middlewares/Exists.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import DataEngine from './DataEngine';
import { tripRequests } from '../database/models';

import { tripRequests, userProfile } from '../database/models';
import Customize from '../helpers/Customize';
/**
* @export
* @class Exists
Expand Down Expand Up @@ -45,7 +45,27 @@ class Exists {
'The trip request doen\'t exist'
);
}
}


/**
* check is the request exist
* @static
* @param {object} req request object
* @param {object} res response object
* @param {object} next next
* @memberof Exists
* @returns {object} data
*/
static async getLineManager(req, res, next) {
// const { managerId } = req.body;
const { id } = req.user;
const userIdProfile = await userProfile.findOne({ where: { userId: id } });
if (!userIdProfile.managerId) {
return Customize.errorMessage(req, res, 'Please update your line manager', 404);
}
const { managerId } = userProfile;
req.body.managerId = managerId;
return next();
}
}
export default Exists;
29 changes: 29 additions & 0 deletions src/middlewares/TripMiddlewares.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { userProfile } from '../database/models';
import Customize from '../helpers/Customize';

/**
* @export
* @class TripMiddleware
*/
class TripMiddleware {
/**
* Get line manager for trip requests
* @static
* @param {object} req request object
* @param {object} res response object
* @param {object} next next
* @memberof TripMiddleware
* @returns {object} data
*/
static async getLineManager(req, res, next) {
const { id } = req.user;
const userIdProfile = await userProfile.findOne({ where: { userId: id } });
if (!userIdProfile.managerId) {
return Customize.errorMessage(req, res, 'Please update your line manager', 404);
}
const { managerId } = userProfile;
req.body.managerId = managerId;
return next();
}
}
export default TripMiddleware;
14 changes: 0 additions & 14 deletions src/middlewares/Validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,6 @@ class Validate {
];
}

/**
* Validate input
* @static
* @returns {object} errors
*/
static oneWayTripRules() {
return [
check('originId', 'originId should be an integer').isNumeric(),
check('destinationId', 'destinationId should be an integer').isNumeric(),
check('reason', 'Reason should be a minimum of 2 letters').isString().isLength({ min: 2 }),
check('startDate', 'Start date should be a valid date after today(YY-MM-DD) ').isAfter().isISO8601(),
];
}

/**
* Validate input
* @static
Expand Down
7 changes: 3 additions & 4 deletions src/middlewares/ValidateTrip.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ export default class ValidateTrip {

const allCities = await cities.findAll({ attributes: ['id'], raw: true, });
const userCitiesArr = [];

const AllCitiesArr = allCities.map((singleCity) => singleCity.id);
itinerary.forEach((singleCity) => userCitiesArr.push(singleCity.originId, singleCity.destinationId));

const AllCitiesArr = allCities.map(singleCity => singleCity.id);
itinerary
.forEach(singleCity => userCitiesArr.push(singleCity.originId, singleCity.destinationId));
const cityExist = userCitiesArr.every((val) => AllCitiesArr.indexOf(val) !== -1);

if (!cityExist) {
Expand Down
1 change: 0 additions & 1 deletion src/middlewares/isRoledifferent.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const isRoledifferent = async (req, res, next) => {
let status;

if (existingEmail === assignEmail) {

status = 403;
return Customize.errorMessage(req, res, 'you are not allowed to change your access', status);
}
Expand Down
57 changes: 55 additions & 2 deletions src/routes/api/tripRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,32 @@ import Exists from '../../middlewares/Exists';
import Conflict from '../../middlewares/Conflict';
import isUserVerified from '../../middlewares/isUserVerified';
import { IsOwnerOfTrip, IsTripApproved } from '../../middlewares/findUsers';
import TripMiddleware from '../../middlewares/TripMiddlewares';
import VerifyUserRoles from '../../middlewares/VerifyUserRoles';

const tripRouter = express.Router();
const { verifyToken } = AuthenticateToken;

const { returnTripController, OneWayTripController, editTrip } = TripController;
const {
returnTripController,
OneWayTripController,
editTrip,
getRequestsByManager
} = TripController;
const { isTripRequestFound } = Conflict;
const { getLineManager } = TripMiddleware;

tripRouter.post('/oneway',
verifyToken,
Validate.requestOnewayTripRules(),
checkInputDataError,
getLineManager,
ValidateTrip.checkIfOriginDestinationExists,
ValidateTrip.checkIfOriginSameAsDestination,
ValidateTrip.checkMultiCityForSimilarRequests,
ValidateTrip.checkForSimilarRequests,
ValidateTrip.checkForSimilarRequestsDateRange,
OneWayTripController);

/**
* @swagger
Expand Down Expand Up @@ -70,7 +89,19 @@ tripRouter
OneWayTripController
);


tripRouter.post(
'/multicity',
AuthenticateToken.verifyToken,
Validate.requestMultiTripRules(),
checkInputDataError,
getLineManager,
ValidateTrip.checkIfOriginDestinationExists,
ValidateTrip.checkIfOriginSameAsDestination,
ValidateTrip.checkMultiCityForSimilarRequests,
ValidateTrip.checkForSimilarRequests,
ValidateTrip.checkForSimilarRequestsDateRange,
TripController.requestTrip
);
/**
* @swagger
*
Expand Down Expand Up @@ -178,6 +209,19 @@ tripRouter
TripController.approveTrip
);

tripRouter
.post(
'/twoWay',
verifyToken,
Validate.twoWayTripRules(),
checkInputDataError,
ValidateTrip.checkIfOriginDestinationExists,
ValidateTrip.checkIfOriginSameAsDestination,
ValidateTrip.checkMultiCityForSimilarRequests,
ValidateTrip.checkForSimilarRequests,
ValidateTrip.checkForSimilarRequestsDateRange,
returnTripController
);

/**
* @swagger
Expand Down Expand Up @@ -251,13 +295,22 @@ tripRouter
ValidateTrip.checkForSimilarRequestsDateRange,
returnTripController
);
tripRouter.get(
'/requests',
verifyToken,
VerifyUserRoles.isManager,
getRequestsByManager
);

/**
* @swagger
*
* /trips/:id:
* get:
* summary: Available trip requests
* /trips/requests:
* get:
* summary: Available requests to manager for approval
* tags: [Trip]
* parameters:
* - name: token
Expand Down
Loading

0 comments on commit 92529f1

Please sign in to comment.