Tarea #600 loggable

This commit is contained in:
Gerard 2018-10-03 09:37:34 +02:00
parent 98d035a961
commit 43cbdefa22
5 changed files with 217 additions and 1 deletions

View File

@ -0,0 +1,50 @@
{
"name": "ClientLog",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientLog"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"forceId": false
},
"originFk": {
"type": "Number",
"required": true
},
"userFk": {
"type": "Number",
"required": true
},
"action": {
"type": "String",
"required": true
},
"model": {
"type": "String",
"required": true
},
"oldInstance": {
"type": "Object",
"required": true
},
"newInstance": {
"type": "Object",
"required": true
},
"creationDate": {
"type": "Date"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "userFk"
}
}
}

View File

@ -1,6 +1,9 @@
{
"name": "Client",
"base": "VnModel",
"base": "Loggable",
"log": {
"model":"ClientLog"
},
"options": {
"mysql": {
"table": "client"

View File

@ -0,0 +1,155 @@
const pick = require('object.pick');
const LoopBackContext = require('loopback-context');
module.exports = function(Self) {
Self.setup = function() {
Self.super_.setup.call(this);
};
Self.observe('after save', async function(ctx) {
const loopBackContext = LoopBackContext.getCurrentContext();
await logInModel(ctx, loopBackContext);
});
Self.observe('before save', async function(ctx) {
let oldInstance;
let oldInstanceFk;
let newInstance;
if (ctx.data) {
oldInstanceFk = pick(ctx.currentInstance, Object.keys(ctx.data));
newInstance = await fkToValue(ctx.data, ctx);
oldInstance = await fkToValue(oldInstanceFk, ctx);
}
if (ctx.isNewInstance) {
newInstance = await fkToValue(ctx.instance.__data, ctx);
}
ctx.hookState.oldInstance = oldInstance;
ctx.hookState.newInstance = newInstance;
});
/* Self.observe('before delete', async function(ctx, next) {
let oldInstance;
if (ctx.instance) {
oldInstance = await fkToValue(ctx.data, ctx);
}
await logInModel(ctx);
next();
});
Self.observe('after delete', async function(ctx, next) {
let oldInstance;
if (ctx.instance) {
oldInstance = await fkToValue(ctx.data, ctx);
}
await logInModel(ctx);
next();
});
*/
async function fkToValue(instance, ctx) {
let result = {};
for (let key in instance) {
if (key == 'id') continue;
let val = instance[key];
if (val === undefined) continue;
for (let key1 in ctx.Model.relations) {
let val1 = ctx.Model.relations[key1];
if (val1.keyFrom == key) {
let recordSet = await val1.modelTo.findById(val);
val = recordSet.name; // FIXME preparar todos los modelos con campo name
break;
}
}
result[key] = val;
}
return result;
}
async function logInModel(ctx, loopBackContext) {
let definition = ctx.Model.definition;
let primaryKey;
for (let property in definition.properties) {
if (definition.properties[property].id) {
primaryKey = property;
break;
}
}
if (!primaryKey) throw new Error('Primary key not found');
let originId;
if (definition.settings.log.relation) {
// RELATIONS LOG
primaryKey = ctx.Model.relations[definition.settings.log.relation].keyFrom;
if(ctx.where && ctx.where[primaryKey])
originId = ctx.where[primaryKey]
else
originId = ctx.instance[primaryKey];
} else {
if (ctx.instance) {
originId = ctx.instance.id;
} else {
originId = ctx.currentInstance.id;
}
}
// This adds the originDescription field if it doesnt exists in the instances
let originDescription = definition.settings.log.originDescription;
if (originDescription && (!ctx.instance || !ctx.instance[originDescription]))
await Self.modelBuilder.models[definition.name].findById()
if (ctx.hookState.oldInstance && !ctx.hookState.oldInstance[originDescription]){
ctx.hookState.oldInstance[originDescription] = ctx.instance[originDescription];
ctx.hookState.newInstance[originDescription] = ctx.instance[originDescription];
}
// This put some order in the intances putting the originDescription in first place
let oldInstance = {};
if (ctx.hookState.oldInstance) {
oldInstance[originDescription] = ctx.hookState.oldInstance[originDescription];
delete ctx.hookState.oldInstance[originDescription];
Object.assign(oldInstance, ctx.hookState.oldInstance);
}
let newInstance = {};
if (ctx.hookState.newInstance) {
newInstance[originDescription] = ctx.hookState.newInstance[originDescription];
delete ctx.hookState.newInstance[originDescription];
Object.assign(newInstance, ctx.hookState.newInstance)
}
let action = setActionType(ctx);
let userFk = loopBackContext.active.accessToken.userId;
let logRecord = {
originFk: originId,
userFk: userFk,
model: ctx.Model.definition.name,
action: action,
oldInstance: oldInstance,
newInstance: newInstance
};
let logModel = definition.settings.log.model
await Self.modelBuilder.models[logModel].create(logRecord);
}
function setActionType(ctx) {
let oldInstance = ctx.hookState.oldInstance;
let newInstance = ctx.hookState.newInstance;
if (oldInstance && newInstance) {
return 'update';
} else if (!oldInstance && newInstance) {
return 'insert';
}
}
};

View File

@ -0,0 +1,5 @@
{
"name": "Loggable",
"base": "VnModel",
"validateUpsert": true
}

View File

@ -45,6 +45,9 @@
"Client": {
"dataSource": "vn"
},
"ClientLog": {
"dataSource": "vn"
},
"ClientCreditLimit": {
"dataSource": "vn"
},