Skip to content

Commit

Permalink
Bg(tables relation): fix trip and request relation
Browse files Browse the repository at this point in the history
- Add requestId into trip model
- Remove tripId from both trip and request models
- Refactor the code to reflect the changes

[starts #170804355]
  • Loading branch information
gadishimwe committed Jan 21, 2020
1 parent 85e5285 commit 5341e8a
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 106 deletions.
41 changes: 16 additions & 25 deletions src/controllers/trip.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ class TripController {
* @returns {response} @memberof Trips
*/
static async requestOneWayTrip(req, res) {
const { dataValues } = await TripService.createTrip({
...req.body, tripId: req.tripId, userId: req.userData.id, tripType: 'one-way', status: 'pending'
const { lineManagerId } = await UserService.findUserByProperty(req.userData.id);
const newRequest = await RequestService.createRequest({ requesterId: req.userData.id, status: 'pending', lineManagerId });

const newTrip = await TripService.createTrip({
...req.body, requestId: newRequest.get().id, userId: req.userData.id, tripType: 'one-way', status: 'pending'
});
const { updatedAt, createdAt, ...newTrip } = dataValues;
ResponseService.setSuccess(201, 'Trip is successfully created', newTrip);
ResponseService.setSuccess(201, 'Trip is successfully created', { newTrip, newRequest });
return ResponseService.send(res);
}

Expand All @@ -35,24 +37,13 @@ class TripController {
* @returns {response} @memberof Trips
*/
static async requestReturnTrip(req, res) {
const {
originId, destinationId, departureDate, returnDate, travelReasons, accommodationId
} = req.body;
const { lineManagerId } = await UserService.findUserByProperty(req.userData.id);
const newRequest = await RequestService.createRequest({ requesterId: req.userData.id, status: 'pending', lineManagerId });

const returnTrip = {
tripId: req.tripId,
userId: req.userData.id,
tripType: 'return-trip',
originId,
destinationId,
departureDate,
returnDate,
travelReasons,
accommodationId,
status: 'pending'
};
await TripService.createTrip(returnTrip);
ResponseService.setSuccess(201, 'Trip created successfully', returnTrip);
const returnTrip = await TripService.createTrip({
...req.body, requestId: newRequest.get().id, userId: req.userData.id, tripType: 'return-trip', status: 'pending'
});
ResponseService.setSuccess(201, 'Trip created successfully', { newTrip: returnTrip, newRequest });
return ResponseService.send(res);
}

Expand Down Expand Up @@ -84,16 +75,16 @@ class TripController {
* @returns {response} @memberof Trips
*/
static async requestMultiCityTrip(req, res) {
const newMultiCityTrip = req.body.map((trip) => ({ ...trip, tripId: req.tripId, userId: req.userData.id, tripType: 'multi-city' }));
const { lineManagerId } = await UserService.findUserByProperty(req.userData.id);
const newRequest = await RequestService.createRequest({ requesterId: req.userData.id, status: 'pending', lineManagerId });

const newMultiCityTrip = req.body.map((trip) => ({ ...trip, userId: req.userData.id, requestId: newRequest.get().id, tripType: 'multi-city' }));
const newTrips = await TripService.createMultiCityTrip(newMultiCityTrip);
const newTripArray = newTrips.map((trip) => {
const { dataValues } = trip;
const { updatedAt, createdAt, ...newTrip } = dataValues;
return newTrip;
});
const { lineManagerId } = await UserService.findUserByProperty(req.userData.id);
const { dataValues } = await RequestService.createRequest({ requesterId: newMultiCityTrip[0].userId, tripId: req.tripId, status: 'pending', lineManagerId });
const { updatedAt, createdAt, ...newRequest } = dataValues;
ResponseService.setSuccess(201, 'Trip request is successfully created', { newTrip: newTripArray, newRequest });
return ResponseService.send(res);
}
Expand Down
4 changes: 2 additions & 2 deletions src/migrations/20191231150619-create-trip.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ export const up = (queryInterface, Sequelize) => queryInterface.createTable('Tri
tripType: {
type: Sequelize.STRING
},
tripId: {
type: Sequelize.BIGINT
requestId: {
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER
Expand Down
3 changes: 0 additions & 3 deletions src/migrations/20200101101824-create-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ export const up = (queryInterface, Sequelize) => queryInterface.createTable('Req
requesterId: {
type: Sequelize.INTEGER
},
tripId: {
type: Sequelize.BIGINT
},
status: {
type: Sequelize.STRING
},
Expand Down
2 changes: 0 additions & 2 deletions src/models/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import emitter from '../helpers/eventEmmiters/emitter';
export default (sequelize, DataTypes) => {
const Request = sequelize.define('Request', {
requesterId: DataTypes.INTEGER,
tripId: DataTypes.BIGINT,
status: DataTypes.STRING,
lineManagerId: DataTypes.INTEGER
}, {});
Request.associate = (models) => {
Request.belongsTo(models.Users, { foreignKey: 'requesterId', targetKey: 'id' });
Request.belongsTo(models.Trip, { foreignKey: 'tripId', targetKey: 'tripId' });
};
Request.afterUpdate((data) => {
emitter.emit('request-updated', data);
Expand Down
2 changes: 1 addition & 1 deletion src/models/trip.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import emitter from '../helpers/eventEmmiters/emitter';
export default (sequelize, DataTypes) => {
const Trip = sequelize.define('Trip', {
tripType: DataTypes.STRING,
tripId: DataTypes.BIGINT,
requestId: DataTypes.INTEGER,
userId: DataTypes.INTEGER,
originId: DataTypes.INTEGER,
destinationId: DataTypes.INTEGER,
Expand Down
2 changes: 1 addition & 1 deletion src/tests/fixtures/trip.fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const trip = {
const newTrip = {
originId: faker.random.number({ min: 1, max: 9 }),
destinationId: faker.random.number({ min: 1, max: 9 }),
departureDate: faker.date.future(),
departureDate: '2020-02-03',
travelReasons: faker.lorem.sentence(),
accommodationId: faker.random.number()
};
Expand Down
10 changes: 5 additions & 5 deletions src/tests/notification/notification.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,11 @@ describe('Tests notification preferences', () => {
.end((err, res) => {
expect(res).to.have.status(201);
expect(res.body).to.have.property('data');
expect(res.body.data).to.have.property('id');
expect(res.body.data).to.have.property('originId').equal(newTrip.originId);
expect(res.body.data).to.have.property('destinationId').equal(newTrip.destinationId);
expect(res.body.data).to.have.property('travelReasons').equal(newTrip.travelReasons);
expect(res.body.data).to.have.property('accommodationId').equal(newTrip.accommodationId);
expect(res.body.data.newTrip).to.have.property('id');
expect(res.body.data.newTrip).to.have.property('originId').equal(newTrip.originId);
expect(res.body.data.newTrip).to.have.property('destinationId').equal(newTrip.destinationId);
expect(res.body.data.newTrip).to.have.property('travelReasons').equal(newTrip.travelReasons);
expect(res.body.data.newTrip).to.have.property('accommodationId').equal(newTrip.accommodationId);
done();
});
});
Expand Down
10 changes: 5 additions & 5 deletions src/tests/trip/one-way-trip.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ describe('Test one way trip:', () => {
.end((err, res) => {
expect(res).to.have.status(201);
expect(res.body).to.have.property('data');
expect(res.body.data).to.have.property('id');
expect(res.body.data).to.have.property('originId').equal(newTrip.originId);
expect(res.body.data).to.have.property('destinationId').equal(newTrip.destinationId);
expect(res.body.data).to.have.property('travelReasons').equal(newTrip.travelReasons);
expect(res.body.data).to.have.property('accommodationId').equal(newTrip.accommodationId);
expect(res.body.data.newTrip).to.have.property('id');
expect(res.body.data.newTrip).to.have.property('originId').equal(newTrip.originId);
expect(res.body.data.newTrip).to.have.property('destinationId').equal(newTrip.destinationId);
expect(res.body.data.newTrip).to.have.property('travelReasons').equal(newTrip.travelReasons);
expect(res.body.data.newTrip).to.have.property('accommodationId').equal(newTrip.accommodationId);
done();
});
});
Expand Down
19 changes: 11 additions & 8 deletions src/validations/multi-city-trip.validation.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import joiBase from '@hapi/joi';
import joiDate from '@hapi/joi-date';
import { Op } from 'sequelize';
import ResponseService from '../services/response.service';
import RequestService from '../services/trip.service';
import TripService from '../services/trip.service';
import LocationService from '../services/location.service';

const Joi = joiBase.extend(joiDate);
Expand Down Expand Up @@ -58,22 +59,24 @@ export default async (req, res, next) => {
ResponseService.setError(400, allErrorMessages);
return ResponseService.send(res);
}
let tripId = `${req.userData.id}${new Date().getFullYear()}${new Date().getMonth()}${new Date().getDate()}`;
req.body.forEach(trip => {
tripId += `${trip.destinationId}`;
});
const filteredTrips = req.body.filter((trip, index) => index !== 0);
filteredTrips.forEach((trip, index) => {
if (req.body[index + 1].originId !== req.body[index].destinationId) {
ResponseService.setError(400, 'Next origin location have to be the same as previous destination location');
return ResponseService.send(res);
}
});
const tripExist = await RequestService.findTripByProperty({ tripId });
if (tripExist) {
const trips = await Promise.all(req.body.map(async (trip) => {
const tripExist = await TripService.findTripByProperty({
originId: trip.originId,
destinationId: trip.destinationId,
departureDate: { [Op.between]: [new Date(`${trip.departureDate}T00:00:00.000Z`), new Date(`${trip.departureDate}T23:59:59.999Z`)] }
});
return tripExist;
}));
if (trips[0] !== null) {
ResponseService.setError(409, 'Trip request already created');
return ResponseService.send(res);
}
req.tripId = tripId;
next();
};
35 changes: 15 additions & 20 deletions src/validations/one-way-trip.validation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import joiBase from '@hapi/joi';
import joiDate from '@hapi/joi-date';
import { Op } from 'sequelize';
import ResponseService from '../services/response.service';
import TripService from '../services/trip.service';
import LocationService from '../services/location.service';
Expand Down Expand Up @@ -31,33 +32,27 @@ export default async (req, res, next) => {
}).options({ abortEarly: false });

const results = schema.validate({ ...req.body });
const errorMessages = [];
if (results.error) {
results.error.details.forEach((error) => {
errorMessages.push(error.message.replace(/[^a-zA-Z0-9 .-]/g, ''));
});
}

if (req.body.originId && req.body.destinationId) {
const locations = [req.body.originId, req.body.destinationId];
await Promise.all(locations.map(async loc => {
const isLocationExist = await LocationService.findLocationByProperty({ id: loc });
if (!isLocationExist) {
errorMessages.push(`location with id ${loc} is not available`);
}
}));
}

if (errorMessages.length !== 0) {
const errorMessages = results.error.details.map((error) => error.message.replace(/[^a-zA-Z0-9 .-]/g, ''));
ResponseService.setError(400, errorMessages);
return ResponseService.send(res);
}
const tripId = `${req.userData.id}${new Date().getFullYear()}${new Date().getMonth()}${new Date().getDate()}${req.body.destinationId}`;
const tripExist = await TripService.findTripByProperty({ tripId });
const locations = [req.body.originId, req.body.destinationId];
await Promise.all(locations.map(async loc => {
const isLocationExist = await LocationService.findLocationByProperty({ id: loc });
if (!isLocationExist) {
ResponseService.setError(400, `location with id ${loc} is not available`);
return ResponseService.send(res);
}
}));
const tripExist = await TripService.findTripByProperty({
originId: req.body.originId,
destinationId: req.body.destinationId,
departureDate: { [Op.between]: [new Date(`${req.body.departureDate}T00:00:00.000Z`), new Date(`${req.body.departureDate}T23:59:59.999Z`)] }
});
if (tripExist) {
ResponseService.setError(409, 'This trip request was already created');
return ResponseService.send(res);
}
req.tripId = tripId;
next();
};
53 changes: 19 additions & 34 deletions src/validations/trip.validation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import joiBase from '@hapi/joi';
import joiDate from '@hapi/joi-date';
import { Op } from 'sequelize';
import ResponseService from '../services/response.service';
import TripService from '../services/trip.service';
import LocationService from '../services/location.service';
Expand All @@ -13,10 +14,6 @@ const Joi = joiBase.extend(joiDate);
* @returns {returns} this is the function for validation
*/
async function tripValidation(req, res, next) {
const {
departureDate,
returnDate,
} = req.body;
const schema = Joi.object({
originId: Joi.number()
.required(),
Expand All @@ -25,14 +22,14 @@ async function tripValidation(req, res, next) {
departureDate: Joi.date().greater('now').utc().format('YYYY-MM-DD')
.required()
.messages({
'date.greater': 'Date should be greater than today\'s date',
'date.greater': 'departure date should be greater than today\'s date',
'date.format': 'Date must be in YYYY-MM-DD format',
'any.required': 'Travel date is required'
}),
returnDate: Joi.date().greater('now').utc().format('YYYY-MM-DD')
returnDate: Joi.date().greater(Joi.ref('departureDate')).utc().format('YYYY-MM-DD')
.required()
.messages({
'date.greater': 'Date should be greater than today\'s date',
'any.ref': 'return date should be greater than departure date',
'date.format': 'Date must be in YYYY-MM-DD format',
'any.required': 'Return date is required'
}),
Expand All @@ -45,41 +42,29 @@ async function tripValidation(req, res, next) {
}),
accommodationId: Joi.number()
});

const { error } = schema.validate(req.body);
const errorMessages = [];
if (error) {
error.details.forEach((err) => {
errorMessages.push(err.message.replace(/[^a-zA-Z0-9 .-]/g, ''));
});
}

if (req.body.originId && req.body.destinationId) {
const locations = [req.body.originId, req.body.destinationId];
await Promise.all(locations.map(async loc => {
const isLocationExist = await LocationService.findLocationByProperty({ id: loc });
if (!isLocationExist) {
errorMessages.push(`location with id ${loc} is not available`);
}
}));
}

if (departureDate > returnDate) {
ResponseService.setError(400, 'Travel date can not be greater than return date');
return ResponseService.send(res);
}
if (errorMessages.length !== 0) {
const errorMessages = error.details.map((err) => err.message.replace(/[^a-zA-Z0-9 .-]/g, ''));
ResponseService.setError(400, errorMessages);
return ResponseService.send(res);
}

const tripId = `${req.userData.id}${new Date().getFullYear()}${new Date().getMonth()}${new Date().getDate()}${req.body.destinationId}`;
const existTrip = await TripService.findTripByProperty({ tripId });
if (existTrip) {
const locations = [req.body.originId, req.body.destinationId];
await Promise.all(locations.map(async loc => {
const isLocationExist = await LocationService.findLocationByProperty({ id: loc });
if (!isLocationExist) {
ResponseService.setError(400, `location with id ${loc} is not available`);
return ResponseService.send(res);
}
}));
const tripExist = await TripService.findTripByProperty({
originId: req.body.originId,
destinationId: req.body.destinationId,
departureDate: { [Op.between]: [new Date(`${req.body.departureDate}T00:00:00.000Z`), new Date(`${req.body.departureDate}T23:59:59.999Z`)] }
});
if (tripExist) {
ResponseService.setError(409, 'Trip request already created');
return ResponseService.send(res);
}
req.tripId = tripId;
next();
}

Expand Down

0 comments on commit 5341e8a

Please sign in to comment.