diff --git a/backend/app/bologger.js b/backend/app/bologger.js index d148f1afd..a99f393ae 100644 --- a/backend/app/bologger.js +++ b/backend/app/bologger.js @@ -10,18 +10,31 @@ var co = require('co'), thunkify = require('thunkify'), Query = require('app/util').Query, + sql = require('sql'), query = new Query(), thunkQuery = thunkify(query); function BoLogger() { + this.data = {}; } +BoLogger.prototype.init = function* (object) { + this.data.essence = yield common.getEssenceId(object); +}; + +BoLogger.prototype.extend = function (data) { + this.data = (_.extend(this.data, _.pick(data, Log.insertCols))); +}; + BoLogger.prototype.log = function (data) { - co(function* () { - console.log(data); - data.essence = yield * common.getEssenceId(data.object); - var id = yield thunkQuery(Log.insert(_.pick(data, Log.insertCols)).returning(Log.id)); + co.call(this, function* () { + //data.essence = yield * common.getEssenceId(data.object); + if (data.object) { + yield this.init(data.object); + } + this.extend(data) + var id = yield thunkQuery(Log.insert(this.data).returning(Log.id)); return data; }).then(function (data) { next(); @@ -30,5 +43,12 @@ BoLogger.prototype.log = function (data) { }); }; +BoLogger.prototype.error = function (data, result) { + this.log(_.extend(data, {error: true, result: result})); +}; + +var getEssenceId = function* (essenceName) { + return yield thunkQuery(Essence.select().from(Essence).where([sql.functions.UPPER(Essence.name).equals(essenceName.toUpperCase())])); +}; module.exports = BoLogger; diff --git a/backend/app/controllers/discussions.js b/backend/app/controllers/discussions.js index e814818b9..02242a869 100644 --- a/backend/app/controllers/discussions.js +++ b/backend/app/controllers/discussions.js @@ -3,6 +3,8 @@ var auth = require('app/auth'), config = require('config'), common = require('app/queries/common'), + BoLogger = require('app/bologger'), + bologger = new BoLogger(), Product = require('app/models/products'), ProductUOA = require('app/models/product_uoa'), Project = require('app/models/projects'), @@ -67,6 +69,9 @@ module.exports = { select: function (req, res, next) { co(function* () { + var task = yield * common.getTask(req.query.taskId); + var productId = task.productId; + var uoaId = task.uoaId; var selectFields = 'SELECT '+ '"Discussions".*, '+ @@ -89,9 +94,9 @@ module.exports = { selectWhere = setWhereInt(selectWhere, req.query.questionId, 'Discussions', 'questionId'); selectWhere = setWhereInt(selectWhere, req.query.userId, 'Discussions', 'userId'); selectWhere = setWhereInt(selectWhere, req.query.userFromId, 'Discussions', 'userFromId'); - selectWhere = setWhereInt(selectWhere, req.query.taskId, 'Discussions', 'taskId'); - selectWhere = setWhereInt(selectWhere, req.query.uoaId, 'UnitOfAnalysis', 'id'); - selectWhere = setWhereInt(selectWhere, req.query.productId, 'Products', 'id'); + //selectWhere = setWhereInt(selectWhere, req.query.taskId, 'Discussions', 'taskId'); + selectWhere = setWhereInt(selectWhere, uoaId, 'UnitOfAnalysis', 'id'); + selectWhere = setWhereInt(selectWhere, productId, 'Products', 'id'); selectWhere = setWhereInt(selectWhere, req.query.stepId, 'WorkflowSteps', 'id'); selectWhere = setWhereInt(selectWhere, req.query.surveyId, 'Surveys', 'id'); @@ -112,6 +117,13 @@ module.exports = { req.body = _.extend(req.body, {userFromId: req.user.id}); // add from user id req.body = _.pick(req.body, Discussion.insertCols); // insert only columns that may be inserted var result = yield thunkQuery(Discussion.insert(req.body).returning(Discussion.id)); + bologger.log({ + user: req.user.id, + action: 'insert', + object: 'discussions', + entity: result[0].id, + info: 'Add discussion`s entry' + }); var entry=_.first(result); var newStep; if (isReturn) { @@ -174,14 +186,20 @@ module.exports = { yield * checkUpdate(req); req.body = _.extend(req.body, {updated: new Date()}); // update `updated` req.body = _.pick(req.body, Discussion.updateCols); // update only columns that may be updated - var result = yield thunkQuery(Discussion.update(req.body).where(Discussion.id.equals(req.params.id))); + var result = yield thunkQuery(Discussion.update(req.body).where(Discussion.id.equals(req.params.id)).returning(Discussion.id)); + bologger.log({ + user: req.user.id, + action: 'update', + object: 'discussions', + entity: result[0].id, + info: 'Update body of discussion`s entry' + }); var entry = yield * common.getDiscussionEntry(req.params.id); var essenceId = yield * common.getEssenceId('Discussions'); var userFrom = yield * common.getUser(req.user.id); var userTo = yield * common.getUser(entry.userId); // static blindRewiev - var taskId = yield * checkOneId(req.body.taskId, Task, 'id', 'taskId', 'Task'); // ToDo: exclude unwanted query - var task = yield * common.getTask(taskId); + var task = yield * common.getTask(entry.taskId); var productId = task.productId; var uoaId = task.uoaId; var step4userTo = yield * getUserToStep(productId, uoaId, userTo.id); @@ -227,6 +245,13 @@ module.exports = { co(function* () { return yield thunkQuery(Discussion.delete().where(Discussion.id.equals(req.params.id))); }).then(function (data) { + bologger.log({ + user: req.user.id, + action: 'delete', + object: 'discussions', + entity: req.params.id, + info: 'Delete discussion`s entry' + }); res.status(204).end(); }, function (err) { next(err); @@ -440,7 +465,7 @@ function* getUserList(user, taskId, productId, uoaId, currentStep, tag) { '"Tasks"."productId" as productid, '+ '"Tasks"."uoaId" as uoaid '+ 'FROM "Discussions" ' + - 'INNER JOIN "Tasks" ON "Discussions"."returnTaskId" = "Tasks"."id" '+ + 'INNER JOIN "Tasks" ON "Discussions"."taskId" = "Tasks"."id" '+ 'INNER JOIN "WorkflowSteps" ON "Tasks"."stepId" = "WorkflowSteps"."id" '+ 'INNER JOIN "Users" ON "Tasks"."userId" = "Users"."id" '+ 'WHERE "Discussions"."returnTaskId" = ' + taskId.toString() + ' '+ @@ -628,12 +653,28 @@ function* getCurrentStep(taskId) { } function* updateProductUOAStep(object) { - var updateProductUOAQuery = - 'UPDATE "ProductUOA" '+ - 'SET "currentStepId" = ' +object.stepId.toString()+ ' '+ - 'WHERE "productId"= '+object.productId.toString()+ - ' AND "UOAid" = '+object.uoaId.toString(); - return yield thunkQuery(updateProductUOAQuery); + var res = yield thunkQuery(ProductUOA.update({currentStepId: object.stepId}) + .where(ProductUOA.productId.equals(object.productId) + .and(ProductUOA.UOAid.equals(object.uoaId)) + ) + .returning(ProductUOA.currentStepId) + ); + if (_.first(res)) { + bologger.log({ + action: 'update', + object: 'productUOA', + entity: null, + entities: {productId: object.productId, uoaId: object.uoaId, currentStepId: object.stepId}, + info: 'Update current step for survey' + }); + } else { + bologger.error({ + action: 'update', + object: 'productUOA', + entity: null, + info: 'Update current step for survey' + }, 'Couldn`t find survey for (productId, uoaId) = ('+object.productId.toString()+', '+object.uoaId.toString()+')'); + } } function* checkUpdateProductUOAStep(object) { @@ -652,21 +693,50 @@ function* checkUpdateProductUOAStep(object) { '"Tasks"."productId" = '+object.productId.toString(); result = yield thunkQuery(query); if (!_.first(result)) { - var updateProductUOAQuery = - 'UPDATE "ProductUOA" '+ - 'SET "currentStepId" = ' +object.stepId.toString()+ ' '+ - 'WHERE "productId"= '+object.productId.toString()+ - ' AND "UOAid" = '+object.uoaId.toString(); - return yield thunkQuery(updateProductUOAQuery); + var res = yield thunkQuery(ProductUOA.update({currentStepId: object.stepId}) + .where(ProductUOA.productId.equals(object.productId) + .and(ProductUOA.UOAid.equals(object.uoaId)) + ) + .returning(ProductUOA.currentStepId) + ); + if (_.first(res)) { + bologger.log({ + action: 'update', + object: 'productUOA', + entity: null, + entities: {productId: object.productId, uoaId: object.uoaId, currentStepId: object.stepId}, + info: 'Update current step for survey (when resolving)' + }); + } else { + bologger.error({ + action: 'update', + object: 'productUOA', + entity: null, + info: 'Update current step for survey (when resolving)' + }, 'Couldn`t find survey for (productId, uoaId) = ('+object.productId.toString()+', '+object.uoaId.toString()+')'); + } } } function* updateReturnTask(discussionId) { - var updateReturnTaskQuery = - 'UPDATE "Discussions" '+ - 'SET "isResolve" = true, "updated" = now() '+ - 'WHERE "id"= '+discussionId.toString(); - return yield thunkQuery(updateReturnTaskQuery); + var res = yield thunkQuery(Discussion.update({isResolve: true, updated: new Date()}) + .where(Discussion.id.equals(discussionId)) + .returning(Discussion.id) + ); + if (_.first(res)) { + bologger.log({ + action: 'update', + entity: discussionId, + info: 'Update task, that was returned before (resolve task)' + }); + } else { + bologger.error({ + action: 'update', + entity: discussionId, + info: 'Update task, that was returned before (resolve task)' + }, 'Couldn`t find discussion`s entry with id = `'+discussionId+'`'); + + } } function* getUserToStep(productId, uoaId, userId) { diff --git a/backend/app/models/logs.js b/backend/app/models/logs.js index 127f7f5c3..7342d76b3 100644 --- a/backend/app/models/logs.js +++ b/backend/app/models/logs.js @@ -12,7 +12,8 @@ var Log = sql.define({ 'entities', 'quantity', 'info', - 'error' + 'error', + 'result' ] }); Log.insertCols = [ @@ -25,7 +26,8 @@ Log.insertCols = [ 'entities', 'quantity', 'info', - 'error' + 'error', + 'result' ]; module.exports = Log; diff --git a/backend/db_dump/patches/20160319-01-Logs.sql b/backend/db_dump/patches/20160319-01-Logs.sql new file mode 100644 index 000000000..d1527b322 --- /dev/null +++ b/backend/db_dump/patches/20160319-01-Logs.sql @@ -0,0 +1,9 @@ +ALTER TABLE "public"."Logs" +ADD COLUMN "result" varchar; + +ALTER TABLE "public"."Essences" +ALTER COLUMN "name" SET NOT NULL; + +DROP INDEX "Essences_upper_idx"; + +CREATE UNIQUE INDEX "Essences_upper_idx" ON "Essences" (upper(name::text)); diff --git a/backend/db_dump/patches/20160319-02-essences-patch1.sql b/backend/db_dump/patches/20160319-02-essences-patch1.sql new file mode 100644 index 000000000..2abbf1d5a --- /dev/null +++ b/backend/db_dump/patches/20160319-02-essences-patch1.sql @@ -0,0 +1,3 @@ +update "Essences" + set "name" = 'UnitOfAnalysisType' +WHERE "fileName" = 'uoatypes' diff --git a/backend/db_dump/patches/20160319-03-essences.sql b/backend/db_dump/patches/20160319-03-essences.sql new file mode 100644 index 000000000..8d7a56bfd --- /dev/null +++ b/backend/db_dump/patches/20160319-03-essences.sql @@ -0,0 +1,38 @@ +WITH new_values ("tableName","name","fileName","nameField") as ( + values +('Surveys', 'Surveys', 'surveys', 'title'), +('SurveyQuestions', 'Survey Questions', 'survey_questions', 'label'), +('SurveyQuestionOptions', 'Survey Question Options', 'survey_question_options', 'label'), +('SurveyAnswers', 'Survey Answers', 'survey_answers', 'value'), +('Groups', 'Groups', 'groups', 'title'), +('Organizations', 'Organizations', 'organizations', 'name'), +('Tasks', 'Tasks', 'tasks', 'title'), +('WorflowSteps', 'WorflowSteps', 'worflowSteps', 'title'), +('Products', 'Products', 'products', 'title'), +('UnitOfAnalysis', 'UnitOfAnalysis', 'uoas', 'name'), +('UnitOfAnalysisType', 'UnitOfAnalysisType', 'uoatypes', 'name'), +('UnitOfAnalysisClassType', 'UnitOfAnalysisClassType', 'uoaclasstypes', 'name'), +('UnitOfAnalysisTag', 'UnitOfAnalysisTag', 'uoatags', 'name'), +('Projects', 'projects', 'projects', 'codeName'), +('Discussions', 'Discussions', 'discussions', 'name'), +('Users', 'Users', 'users', 'email'), +('Notifications', 'notifications', 'notifications', 'body'), +('ProductUOA', 'productUoa', 'product_uoa', 'productId') +), +upsert as +( + update "Essences" m + set "tableName" = nv."tableName", + "fileName" = nv."fileName", + "nameField" = nv."nameField" + FROM new_values nv + WHERE upper(m."name") = upper(nv."name") + RETURNING m.* +) +-- select * from upsert +INSERT INTO "Essences" ("tableName","name","fileName","nameField") +SELECT "tableName","name","fileName","nameField" +FROM new_values +WHERE NOT EXISTS (SELECT 1 + FROM upsert up + WHERE upper(up."name") = upper(new_values."name"))