This commit is contained in:
David Arranz 2019-07-17 14:07:35 +02:00
parent 965086d2ee
commit a6be1ab427
8 changed files with 239 additions and 121 deletions

View File

@ -2,16 +2,17 @@ const _find = require('./find');
const httpStatus = require('http-status'); const httpStatus = require('http-status');
const { extractParamsFromRequest, handleErrorResponse, handleResultResponse } = require('../../helpers/controller.helper'); const { extractParamsFromRequest, handleErrorResponse, handleResultResponse } = require('../../helpers/controller.helper');
function buildContext(req, res) { function buildContext(req, config) {
return { return {
user: req.user user: req.user,
...config,
} }
} }
const defaultOptions = { const defaultOptions = {
MODULE_NAME: 'default', MODULE_NAME: 'default',
params: { params: {
find: { includeAll: true }, find: { includeAll: false },
findOne: { includeAll: true, paginate: { limit: 1, page: 1 } }, findOne: { includeAll: true, paginate: { limit: 1, page: 1 } },
count: {}, count: {},
} }
@ -24,63 +25,79 @@ const generateControllers = (service, extraControllers = {}, options = {}) => {
}; };
const defaultControllers = { const defaultControllers = {
find: async (req, res, next) => { find: (config) => {
const params = extractParamsFromRequest(req, res, _options.params.find); return async (req, res, next) => {
try { config = config || {
const result = await service.fetchAll(params, buildContext(req, res)); scopes: [],
return handleResultResponse(result.rows, result.count, params, res); };
} catch (error) {
handleErrorResponse(_options.MODULE_NAME, 'find', error, res) const params = extractParamsFromRequest(req, res, _options.params.find);
try {
const result = await service.fetchAll(params, buildContext(req, config));
return handleResultResponse(result.rows, result.count, params, res);
} catch (error) {
handleErrorResponse(_options.MODULE_NAME, 'find', error, res)
}
} }
}, },
findOne: async (req, res, next) => { findOne: (config) => {
const params = extractParamsFromRequest(req, res, _options.params.findOne); return async (req, res, next) => {
const params = extractParamsFromRequest(req, res, _options.params.findOne);
try { try {
const result = await service.fetchOne(params, buildContext(req, res)); const result = await service.fetchOne(params, buildContext(req, config));
return handleResultResponse(result, null, params, res, (result === null) ? httpStatus.NOT_FOUND : httpStatus.OK); return handleResultResponse(result, null, params, res, (result === null) ? httpStatus.NOT_FOUND : httpStatus.OK);
} catch (error) { } catch (error) {
handleErrorResponse(_options.MODULE_NAME, 'findOne', error, res) handleErrorResponse(_options.MODULE_NAME, 'findOne', error, res)
}
} }
}, },
count: async(req, res, next) => { count: (config) => {
const params = extractParamsFromRequest(req, res, _options.params.count); return async(req, res, next) => {
const params = extractParamsFromRequest(req, res, _options.params.count);
try { try {
const result = await service.count(params, buildContext(req, res)); const result = await service.count(params, buildContext(req, config));
return handleResultResponse(result, null, params, res); return handleResultResponse(result, null, params, res);
} catch (error) { } catch (error) {
handleErrorResponse(_options.MODULE_NAME, 'count', error, res) handleErrorResponse(_options.MODULE_NAME, 'count', error, res)
}
} }
}, },
create: async (req, res, next) => { create: (config) => {
try { return async (req, res, next) => {
console.log(req.body); try {
const result = await service.create(req.body, buildContext(req, res)); console.log(req.body);
return handleResultResponse(result, null, null, res, httpStatus.CREATED) const result = await service.create(req.body, buildContext(req, config));
} catch (error) { return handleResultResponse(result, null, null, res, httpStatus.CREATED)
handleErrorResponse(_options.MODULE_NAME, 'create', error, res) } catch (error) {
handleErrorResponse(_options.MODULE_NAME, 'create', error, res)
}
} }
}, },
update: async (req, res, next) => { update: (config) => {
try { return async (req, res, next) => {
const result = await service.update(req.params, req.body, buildContext(req, res)); try {
return handleResultResponse(result, null, req.params, res, httpStatus.OK) const result = await service.update(req.params, req.body, buildContext(req, config));
} catch (error) { return handleResultResponse(result, null, req.params, res, httpStatus.OK)
handleErrorResponse(_options.MODULE_NAME, 'update', error, res) } catch (error) {
handleErrorResponse(_options.MODULE_NAME, 'update', error, res)
}
} }
}, },
delete: async (req, res, next) => { delete: (config) => {
try { return async (req, res, next) => {
const result = await service.delete(req.params, buildContext(req, res)); try {
return handleResultResponse(result, null, req.params, res, httpStatus.NO_CONTENT); const result = await service.delete(req.params, buildContext(req, config));
} catch (error) { return handleResultResponse(result, null, req.params, res, httpStatus.NO_CONTENT);
handleErrorResponse(_options.MODULE_NAME, 'delete', error, res) } catch (error) {
handleErrorResponse(_options.MODULE_NAME, 'delete', error, res)
}
} }
}, },
} }

View File

@ -122,6 +122,8 @@ function hasAssociation(params) {
const defaultOptions = {}; const defaultOptions = {};
const generateService = (model, extraMethods = {}, options = defaultOptions) => { const generateService = (model, extraMethods = {}, options = defaultOptions) => {
const defaultService = { const defaultService = {
fetchAssociation: async(params, context) => { fetchAssociation: async(params, context) => {
const associationName = hasAssociation(params); const associationName = hasAssociation(params);
@ -149,40 +151,56 @@ const generateService = (model, extraMethods = {}, options = defaultOptions) =>
return defaultService.fetchAssociation(params, context) return defaultService.fetchAssociation(params, context)
} else { } else {
const findOptions = parseParamsToFindOptions(params); const findOptions = parseParamsToFindOptions(params);
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'); const result = await model.scope(context.scopes).findAndCountAll(findOptions);
console.log(findOptions);
const result = await model.findAndCountAll(findOptions); if (extraMethods.afterFetchAll) {
console.log(result); return extraMethods.afterFetchAll(result, params, context);
return result; } else {
return result;
}
} }
}, },
fetchOne: async (params, context) => { fetchOne: async (params, context) => {
const findOptions = parseParamsToFindOptions(params); const findOptions = parseParamsToFindOptions(params);
console.log(findOptions);
return await model.findOne({ const result = await model.scope(context.scopes).findOne({
where: findOptions.where, where: findOptions.where,
include: findOptions.include include: findOptions.include
}); });
if (extraMethods.afterFetchOne) {
return extraMethods.afterFetchOne(result, params, context);
} else {
return result;
}
}, },
count: async (params, context) => { count: async (params, context) => {
const findOptions = parseParamsToFindOptions(params); const findOptions = parseParamsToFindOptions(params);
return await model.count(findOptions); const result = await model.scope(context.scopes).count(findOptions);
if (extraMethods.afterCount) {
return extraMethods.afterCount(result, params, context);
} else {
return result;
}
}, },
create: async (values, context) => { create: async (values, context) => {
return await model.create(values); return await model.scope(context.scopes).create(values);
}, },
update: async (params, values, context) => { update: async (params, values, context) => {
const findOptions = parseParamsToFindOptions(params); const findOptions = parseParamsToFindOptions(params);
return await model.update(values, findOptions) return await model.scope(context.scopes).update(values, findOptions)
}, },
delete: async (params, context) => { delete: async (params, context) => {
const findOptions = parseParamsToFindOptions(params); const findOptions = parseParamsToFindOptions(params);
const numAffectedRows = await model.destroy(findOptions); const numAffectedRows = await model.scope(context.scopes).destroy(findOptions);
return (numAffectedRows > 0); return (numAffectedRows > 0);
}, },

View File

@ -16,26 +16,36 @@ const MODULE_NAME = '[event.controller]';
const controllerOptions = { MODULE_NAME }; const controllerOptions = { MODULE_NAME };
const extraControllers = { const extraControllers = {
findNext: async (req, res, next) => { findNext: (config) => {
const params = extractParamsFromRequest(req, res, { includeAll: false }); config = config || {
try { scopes: [],
const result = await eventService.fetch(params, { user: req.user, lapse: 'next' }); }
console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
// Joi validation options return async function (req, res, next) {
const _validationOptions = { const params = extractParamsFromRequest(req, res, { includeAll: false });
abortEarly: false, // abort after the last validation error try {
allowUnknown: true, // allow unknown keys that will be ignored const result = await eventService.fetch(params, {
stripUnknown: true // remove unknown keys from the validated data user: req.user,
}; scopes: config.scopes,
console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa222'); lapse: 'next'
const data = Joi.validate(result.dataValues, eventValidation.EventsListOutputType, _validationOptions); });
console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa333'); console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
// Joi validation options
const _validationOptions = {
abortEarly: false, // abort after the last validation error
allowUnknown: true, // allow unknown keys that will be ignored
stripUnknown: true // remove unknown keys from the validated data
};
console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa222');
const data = Joi.validate(result.dataValues, eventValidation.EventsListOutputType, _validationOptions);
console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa333');
console.log(data); console.log(data);
return handleResultResponse(result, result.count, params, res); return handleResultResponse(result, result.count, params, res);
} catch (error) { } catch (error) {
handleErrorResponse(MODULE_NAME, 'findNext', error, res); handleErrorResponse(MODULE_NAME, 'findNext', error, res);
}
} }
}, },

View File

@ -61,7 +61,7 @@ module.exports = function (sequelize, DataTypes) {
state: { state: {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: false,
defaultValue: 'borrador' defaultValue: 'draft'
}, },
typeId: { typeId: {
type: DataTypes.UUID, type: DataTypes.UUID,
@ -80,7 +80,7 @@ module.exports = function (sequelize, DataTypes) {
url_registration: { url_registration: {
type: DataTypes.STRING, type: DataTypes.STRING,
}, },
marketingList: { marketing_list: {
type: DataTypes.STRING, type: DataTypes.STRING,
}, },
userId: { userId: {
@ -94,39 +94,12 @@ module.exports = function (sequelize, DataTypes) {
timestamps: true, timestamps: true,
defaultScope: { defaultScope: {
//Se pude poner algo en función del usuario????? where: {
state: 'publish'
}
}, },
scopes: {
next: {
where: {
date: {
[Sequelize.Op.gte]: moment().add(1, 'days').startOf('day').utc()
}
},
},
current: {
where: {
date: {
[Sequelize.Op.gte]: moment().startOf('day').utc(),
[Sequelize.Op.lt]: moment().add(1, 'days').startOf('day').utc(),
}
}
},
past: {
where: {
date: {
[Sequelize.Op.lt]: moment().startOf('day').utc()
}
}
},
}
}); });
Event.associate = function (models) { Event.associate = function (models) {
// Event.OverflowEvent = Event.belongsTo(models.Event, { // Event.OverflowEvent = Event.belongsTo(models.Event, {
// as: 'overflowEvent', // as: 'overflowEvent',
@ -140,11 +113,17 @@ module.exports = function (sequelize, DataTypes) {
Event.Comments = Event.hasMany(models.Comment, { Event.Comments = Event.hasMany(models.Comment, {
foreignKey: 'entityId', foreignKey: 'entityId',
scope: {
entityName: 'event'
},
as: "comments" as: "comments"
}); });
Event.Multimedias = Event.hasMany(models.Multimedia, { Event.Multimedias = Event.hasMany(models.Multimedia, {
foreignKey: 'entityId', foreignKey: 'entityId',
scope: {
entityName: 'event'
},
as: { singular: 'multimedia', plural: 'multimedias' }}); as: { singular: 'multimedia', plural: 'multimedias' }});
Event.Reservations = Event.hasMany(models.EventReservation, { foreignKey: 'eventId', as: "reservations" }); Event.Reservations = Event.hasMany(models.EventReservation, { foreignKey: 'eventId', as: "reservations" });
@ -152,5 +131,61 @@ module.exports = function (sequelize, DataTypes) {
Event.Questions = Event.hasMany(models.EventQuestion, { foreignKey: 'eventId', as: "questions" }); Event.Questions = Event.hasMany(models.EventQuestion, { foreignKey: 'eventId', as: "questions" });
}; };
Event.addScope('includeVenue', () => {
return {
include: [
{ model: sequelize.models.Venue, as: 'venue' }
]
}
});
Event.addScope('includeSchedule', () => {
return {
include: [
{ model: sequelize.models.EventSchedule, as: 'schedule' }
]
}
});
Event.addScope('includeSpeakers', () => {
return {
include: [{
model: sequelize.models.EventSchedule,
as: 'schedule',
where: {
speakerId: {
[Sequelize.Op.ne]: null
}
},
include: [{ model: sequelize.models.Speaker, as: 'speaker' }]
}]
}
})
Event.addScope('next', {
where: {
date: {
[Sequelize.Op.gte]: moment().add(1, 'days').startOf('day').utc()
}
},
});
Event.addScope('current', {
where: {
date: {
[Sequelize.Op.gte]: moment().startOf('day').utc(),
[Sequelize.Op.lt]: moment().add(1, 'days').startOf('day').utc(),
}
}
});
Event.addScope('past', {
where: {
date: {
[Sequelize.Op.lt]: moment().startOf('day').utc()
}
}
});
return Event; return Event;
}; };

View File

@ -11,25 +11,32 @@ const SortMiddleware = require('../../middlewares/sort');
const eventController = require('./event.controller'); const eventController = require('./event.controller');
const eventValidation = require('./event.validations'); const eventValidation = require('./event.validations');
const generalInvalidFields = [
'userId', 'createdAt', 'updatedAt',
'assistants', 'confirmed', 'allow_multiple',
'multiple_limit', 'allow_overflow', 'marketing_list',
];
routes.get('/events', routes.get('/events',
isLoggedUser, isLoggedUser,
/*FieldMiddleware.middleware({ FieldMiddleware.middleware({
invalidFields: ['user', 'createdAt'] invalidFields: generalInvalidFields
}),*/ }),
PaginateMiddleware.middleware(), PaginateMiddleware.middleware(),
SortMiddleware.middleware({ default: "-date" }), SortMiddleware.middleware({ default: "-date" }),
eventController.find eventController.find
); );
routes.get('/events/next', routes.get('/events/next',
isLoggedUser, //isLoggedUser,
FieldMiddleware.middleware({ FieldMiddleware.middleware({
invalidFields: ['userId', 'createdAt', 'updatedAt'] invalidFields: generalInvalidFields
}), }),
PaginateMiddleware.middleware(), PaginateMiddleware.middleware(),
SortMiddleware.middleware({ default: "init_available_date" }), SortMiddleware.middleware({ default: "init_available_date" }),
//ScopeMiddleware eventController.find({
eventController.findNext, scopes: ['defaultScope', 'next', 'includeVenue', 'includeSchedule', 'includeSpeakers'],
}),
//eventController.find //eventController.find
// model.scope('next').findAll(); // model.scope('next').findAll();
///SchemaValidator(eventValidation.EventsListOutputType, true), ///SchemaValidator(eventValidation.EventsListOutputType, true),
@ -38,6 +45,9 @@ routes.get('/events/next',
routes.get('/events/pass', routes.get('/events/pass',
isLoggedUser, isLoggedUser,
FieldMiddleware.middleware({
invalidFields: generalInvalidFields
}),
PaginateMiddleware.middleware(), PaginateMiddleware.middleware(),
SortMiddleware.middleware({ default: "-date" }), SortMiddleware.middleware({ default: "-date" }),
eventController.findPass eventController.findPass
@ -45,6 +55,9 @@ routes.get('/events/pass',
routes.get('/events/current', routes.get('/events/current',
isLoggedUser, isLoggedUser,
FieldMiddleware.middleware({
invalidFields: generalInvalidFields
}),
PaginateMiddleware.middleware(), PaginateMiddleware.middleware(),
SortMiddleware.middleware({ default: "init_available_date" }), SortMiddleware.middleware({ default: "init_available_date" }),
eventController.findCurrent eventController.findCurrent
@ -53,6 +66,9 @@ routes.get('/events/current',
routes.get('/events/:id', routes.get('/events/:id',
isLoggedUser, isLoggedUser,
FieldMiddleware.middleware({
invalidFields: generalInvalidFields
}),
FieldMiddleware.middleware({ FieldMiddleware.middleware({
invalidFields: ['createdAt'] invalidFields: ['createdAt']
}), }),

View File

@ -8,11 +8,33 @@ const Sequelize = require('sequelize');
const models = require('../../core/models'); const models = require('../../core/models');
const extraMethods = { const extraMethods = {
fetch: async (params, context) => { afterFetchAll: (result, params, context) => {
const lapse = context.lapse; if (!result.count) {
return result;
}
let rows = result.rows.map(row => row.toJSON());
if (context.scopes.includes('includeSpeakers')) {
rows = rows.map(event => Object.assign({}, event, /*{ schedule: undefined },*/ { speakers: event.schedule.map(schedule => schedule.speaker) }));
}
/*rows.map(event => {
const info = event.schedule
})*/
return {
count: rows.length,
rows: rows
}
},
fetch2: async (params, context) => {
//const lapse = context.lapse;
const findOptions = parseParamsToFindOptions(params); const findOptions = parseParamsToFindOptions(params);
switch (lapse) { /*switch (lapse) {
case 'next': case 'next':
findOptions.where = Object.assign({}, findOptions.where = Object.assign({},
findOptions.where, { findOptions.where, {
@ -40,7 +62,7 @@ const extraMethods = {
break; break;
default: default:
break; break;
} }*/
// Incluir // Incluir
findOptions.include.push({ findOptions.include.push({
@ -73,9 +95,9 @@ const extraMethods = {
state: 'publish' state: 'publish'
}); });
console.log(context);
try { try {
return await models.Event.findAll(findOptions); return await models.Event.scope(context.scopes).findAll(findOptions);
} catch(error) { } catch(error) {
throw error; throw error;
} }

View File

@ -56,7 +56,7 @@ module.exports = function (sequelize, DataTypes) {
type: DataTypes.UUID, type: DataTypes.UUID,
foreignKey: true, foreignKey: true,
}, },
marketingList: { marketing_list: {
type: DataTypes.STRING, type: DataTypes.STRING,
}, },
}, { }, {

View File

@ -208,7 +208,7 @@ CREATE TABLE `events` (
`url_streaming` varchar(255) DEFAULT NULL, `url_streaming` varchar(255) DEFAULT NULL,
`url_poll` varchar(255) DEFAULT NULL, `url_poll` varchar(255) DEFAULT NULL,
`url_registration` varchar(255) DEFAULT NULL, `url_registration` varchar(255) DEFAULT NULL,
`marketingList` varchar(255) DEFAULT NULL, `marketing_list` varchar(255) DEFAULT NULL,
`createdAt` datetime NOT NULL, `createdAt` datetime NOT NULL,
`updatedAt` datetime NOT NULL, `updatedAt` datetime NOT NULL,
`userId` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `userId` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
@ -334,7 +334,7 @@ CREATE TABLE `events_reservations` (
`color` varchar(255) NOT NULL, `color` varchar(255) NOT NULL,
`allow_overflow` tinyint(1) NOT NULL DEFAULT '0', `allow_overflow` tinyint(1) NOT NULL DEFAULT '0',
`overflow_event_reservationId` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `overflow_event_reservationId` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`marketingList` varchar(255) DEFAULT NULL, `marketing_list` varchar(255) DEFAULT NULL,
`createdAt` datetime NOT NULL, `createdAt` datetime NOT NULL,
`updatedAt` datetime NOT NULL, `updatedAt` datetime NOT NULL,
`userId` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `userId` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,