-
{{$ctrl.description}}
+
{{$ctrl.description}}
{{$ctrl.descriptor.id | id}}
diff --git a/front/salix/locale/es.yml b/front/salix/locale/es.yml
index f2d81ee23..ae7eb1da7 100644
--- a/front/salix/locale/es.yml
+++ b/front/salix/locale/es.yml
@@ -42,7 +42,7 @@ Travels: Envíos
Workers: Trabajadores
Routes: Rutas
Locator: Localizador
-Invoices out: Facturas emitidas
+Invoices out: Fact. emitidas
Invoices in: Fact. recibidas
Entries: Entradas
Users: Usuarios
diff --git a/loopback/common/models/loggable.js b/loopback/common/models/loggable.js
index 557aad66a..956762be2 100644
--- a/loopback/common/models/loggable.js
+++ b/loopback/common/models/loggable.js
@@ -25,8 +25,8 @@ module.exports = function(Self) {
if (ctx.data) {
const changes = pick(ctx.currentInstance, Object.keys(ctx.data));
- newInstance = await fkToValue(ctx.data, ctx);
- oldInstance = await fkToValue(changes, ctx);
+ newInstance = ctx.data;
+ oldInstance = changes;
if (ctx.where && !ctx.currentInstance) {
const fields = Object.keys(ctx.data);
@@ -41,7 +41,7 @@ module.exports = function(Self) {
// Get changes from created instance
if (ctx.isNewInstance)
- newInstance = await fkToValue(ctx.instance.__data, ctx);
+ newInstance = ctx.instance.__data;
ctx.hookState.oldInstance = oldInstance;
ctx.hookState.newInstance = newInstance;
@@ -261,6 +261,9 @@ module.exports = function(Self) {
removeUnloggable(definition, oldInstance);
removeUnloggable(definition, newInstance);
+ oldInstance = await fkToValue(oldInstance, ctx);
+ newInstance = await fkToValue(newInstance, ctx);
+
// Prevent log with no new changes
const hasNewChanges = Object.keys(newInstance).length;
if (!hasNewChanges) return;
diff --git a/loopback/locale/en.json b/loopback/locale/en.json
index 65028a8a8..c147e6c10 100644
--- a/loopback/locale/en.json
+++ b/loopback/locale/en.json
@@ -93,5 +93,7 @@
"New ticket request has been created": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}*",
"There's a new urgent ticket": "There's a new urgent ticket: [{{title}}](https://cau.verdnatura.es/WorkOrder.do?woMode=viewWO&woID={{issueId}})",
"Swift / BIC cannot be empty": "Swift / BIC cannot be empty",
- "Role name must be written in camelCase": "Role name must be written in camelCase"
+ "Role name must be written in camelCase": "Role name must be written in camelCase",
+ "Client assignment has changed": "I did change the salesperson ~*\"<{{previousWorkerName}}>\"*~ by *\"<{{currentWorkerName}}>\"* from the client [{{clientName}} ({{clientId}})]({{{url}}})",
+ "None": "None"
}
\ No newline at end of file
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 96858eb4a..b325b9176 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -176,5 +176,7 @@
"Invalid account": "Cuenta inválida",
"Compensation account is empty": "La cuenta para compensar está vacia",
"This genus already exist": "Este genus ya existe",
- "This specie already exist": "Esta especie ya existe"
+ "This specie already exist": "Esta especie ya existe",
+ "Client assignment has changed": "He cambiado el comercial ~*\"<{{previousWorkerName}}>\"*~ por *\"<{{currentWorkerName}}>\"* del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
+ "None": "Ninguno"
}
\ No newline at end of file
diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js
index 1e535a5d7..e1de363b2 100644
--- a/modules/client/back/models/client.js
+++ b/modules/client/back/models/client.js
@@ -227,36 +227,6 @@ module.exports = Self => {
await Self.app.models.ClientCredit.create(newCredit);
}
});
- const app = require('vn-loopback/server/server');
-
- app.on('started', function() {
- let account = app.models.Account;
-
- account.observe('before save', async ctx => {
- if (ctx.isNewInstance) return;
- ctx.hookState.oldInstance = JSON.parse(JSON.stringify(ctx.currentInstance));
- });
-
- account.observe('after save', async ctx => {
- let changes = ctx.data || ctx.instance;
- if (!ctx.isNewInstance && changes) {
- let oldData = ctx.hookState.oldInstance;
- let hasChanges = oldData.name != changes.name || oldData.active != changes.active;
- if (!hasChanges) return;
-
- let userId = ctx.options.accessToken.userId;
- let logRecord = {
- originFk: oldData.id,
- userFk: userId,
- action: 'update',
- changedModel: 'Account',
- oldInstance: {name: oldData.name, active: oldData.active},
- newInstance: {name: changes.name, active: changes.active}
- };
- await Self.app.models.ClientLog.create(logRecord);
- }
- });
- });
Self.observe('after save', async ctx => {
if (ctx.isNewInstance) return;
@@ -303,8 +273,58 @@ module.exports = Self => {
query: params
});
}
+
+ const workerIdBefore = oldInstance.salesPersonFk;
+ const workerIdAfter = newInstance.salesPersonFk;
+ const assignmentChanged = workerIdBefore != workerIdAfter;
+ if (assignmentChanged)
+ await Self.notifyAssignment(instance, workerIdBefore, workerIdAfter);
});
+ // Send notification on client worker assignment
+ Self.notifyAssignment = async function notifyAssignment(client, previousWorkerId, currentWorkerId) {
+ const loopBackContext = LoopBackContext.getCurrentContext();
+ const httpCtx = {req: loopBackContext.active};
+ const httpRequest = httpCtx.req.http.req;
+ const $t = httpRequest.__;
+ const headers = httpRequest.headers;
+ const origin = headers.origin;
+ const models = Self.app.models;
+
+ let previousWorker = {name: $t('None')};
+ let currentWorker = {name: $t('None')};
+ if (previousWorkerId) {
+ const worker = await models.Worker.findById(previousWorkerId, {
+ include: {relation: 'user'}
+ });
+ previousWorker.user = worker && worker.user().name;
+ previousWorker.name = worker && worker.user().nickname;
+ }
+
+ if (currentWorkerId) {
+ const worker = await models.Worker.findById(currentWorkerId, {
+ include: {relation: 'user'}
+ });
+ currentWorker.user = worker && worker.user().name;
+ currentWorker.name = worker && worker.user().nickname;
+ }
+
+ const fullUrl = `${origin}/#!/client/${client.id}/basic-data`;
+ const message = $t('Client assignment has changed', {
+ clientId: client.id,
+ clientName: client.name,
+ url: fullUrl,
+ previousWorkerName: previousWorker.name,
+ currentWorkerName: currentWorker.name
+ });
+
+ if (previousWorkerId)
+ await models.Chat.send(httpCtx, `@${previousWorker.user}`, message);
+
+ if (currentWorkerId)
+ await models.Chat.send(httpCtx, `@${currentWorker.user}`, message);
+ };
+
async function validateCreditChange(ctx, finalState) {
let models = Self.app.models;
let userId = ctx.options.accessToken.userId;
@@ -341,4 +361,34 @@ module.exports = Self => {
if (count <= 0)
throw new UserError('The role cannot set this credit amount');
}
+
+ const app = require('vn-loopback/server/server');
+ app.on('started', function() {
+ let account = app.models.Account;
+
+ account.observe('before save', async ctx => {
+ if (ctx.isNewInstance) return;
+ ctx.hookState.oldInstance = JSON.parse(JSON.stringify(ctx.currentInstance));
+ });
+
+ account.observe('after save', async ctx => {
+ let changes = ctx.data || ctx.instance;
+ if (!ctx.isNewInstance && changes) {
+ let oldData = ctx.hookState.oldInstance;
+ let hasChanges = oldData.name != changes.name || oldData.active != changes.active;
+ if (!hasChanges) return;
+
+ let userId = ctx.options.accessToken.userId;
+ let logRecord = {
+ originFk: oldData.id,
+ userFk: userId,
+ action: 'update',
+ changedModel: 'Account',
+ oldInstance: {name: oldData.name, active: oldData.active},
+ newInstance: {name: changes.name, active: changes.active}
+ };
+ await Self.app.models.ClientLog.create(logRecord);
+ }
+ });
+ });
};
diff --git a/modules/client/back/models/specs/client.spec.js b/modules/client/back/models/specs/client.spec.js
new file mode 100644
index 000000000..a9d479516
--- /dev/null
+++ b/modules/client/back/models/specs/client.spec.js
@@ -0,0 +1,54 @@
+const app = require('vn-loopback/server/server');
+const LoopBackContext = require('loopback-context');
+
+describe('Client Model', () => {
+ const activeCtx = {
+ accessToken: {userId: 9},
+ http: {
+ req: {
+ headers: {origin: 'http://localhost'},
+ [`__`]: value => {
+ return value;
+ }
+ }
+ }
+ };
+ const ctx = {req: activeCtx};
+ const chatModel = app.models.Chat;
+ const client = {id: 101, name: 'Bruce Banner'};
+ const previousWorkerId = 106; // DavidCharlesHaller
+ const currentWorkerId = 107; // HankPym
+
+ beforeEach(() => {
+ spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
+ active: activeCtx
+ });
+ });
+
+ describe('notifyAssignment()', () => {
+ it('should call to the Chat send() method for both workers', async() => {
+ spyOn(chatModel, 'send').and.callThrough();
+
+ await app.models.Client.notifyAssignment(client, previousWorkerId, currentWorkerId);
+
+ expect(chatModel.send).toHaveBeenCalledWith(ctx, '@DavidCharlesHaller', `Client assignment has changed`);
+ expect(chatModel.send).toHaveBeenCalledWith(ctx, '@HankPym', `Client assignment has changed`);
+ });
+
+ it('should call to the Chat send() method for the previous worker', async() => {
+ spyOn(chatModel, 'send').and.callThrough();
+
+ await app.models.Client.notifyAssignment(client, null, currentWorkerId);
+
+ expect(chatModel.send).toHaveBeenCalledWith(ctx, '@HankPym', `Client assignment has changed`);
+ });
+
+ it('should call to the Chat send() method for the current worker', async() => {
+ spyOn(chatModel, 'send').and.callThrough();
+
+ await app.models.Client.notifyAssignment(client, previousWorkerId, null);
+
+ expect(chatModel.send).toHaveBeenCalledWith(ctx, '@DavidCharlesHaller', `Client assignment has changed`);
+ });
+ });
+});
diff --git a/modules/entry/front/buy/locale/es.yml b/modules/entry/front/buy/locale/es.yml
index b5a82948b..c77587758 100644
--- a/modules/entry/front/buy/locale/es.yml
+++ b/modules/entry/front/buy/locale/es.yml
@@ -2,4 +2,5 @@ reference: Referencia
Observation: Observación
Box: Embalaje
Import buys: Importar compras
-Some of the imported buys doesn't have an item: Algunas de las compras importadas no tienen un artículo
\ No newline at end of file
+Some of the imported buys doesn't have an item: Algunas de las compras importadas no tienen un artículo
+JSON files only: Solo ficheros JSON
\ No newline at end of file