Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2840-ticket_card_sale_deprecations
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
1cc4e60bad
|
@ -25,8 +25,8 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
if (ctx.data) {
|
if (ctx.data) {
|
||||||
const changes = pick(ctx.currentInstance, Object.keys(ctx.data));
|
const changes = pick(ctx.currentInstance, Object.keys(ctx.data));
|
||||||
newInstance = await fkToValue(ctx.data, ctx);
|
newInstance = ctx.data;
|
||||||
oldInstance = await fkToValue(changes, ctx);
|
oldInstance = changes;
|
||||||
|
|
||||||
if (ctx.where && !ctx.currentInstance) {
|
if (ctx.where && !ctx.currentInstance) {
|
||||||
const fields = Object.keys(ctx.data);
|
const fields = Object.keys(ctx.data);
|
||||||
|
@ -41,7 +41,7 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
// Get changes from created instance
|
// Get changes from created instance
|
||||||
if (ctx.isNewInstance)
|
if (ctx.isNewInstance)
|
||||||
newInstance = await fkToValue(ctx.instance.__data, ctx);
|
newInstance = ctx.instance.__data;
|
||||||
|
|
||||||
ctx.hookState.oldInstance = oldInstance;
|
ctx.hookState.oldInstance = oldInstance;
|
||||||
ctx.hookState.newInstance = newInstance;
|
ctx.hookState.newInstance = newInstance;
|
||||||
|
@ -261,6 +261,9 @@ module.exports = function(Self) {
|
||||||
removeUnloggable(definition, oldInstance);
|
removeUnloggable(definition, oldInstance);
|
||||||
removeUnloggable(definition, newInstance);
|
removeUnloggable(definition, newInstance);
|
||||||
|
|
||||||
|
oldInstance = await fkToValue(oldInstance, ctx);
|
||||||
|
newInstance = await fkToValue(newInstance, ctx);
|
||||||
|
|
||||||
// Prevent log with no new changes
|
// Prevent log with no new changes
|
||||||
const hasNewChanges = Object.keys(newInstance).length;
|
const hasNewChanges = Object.keys(newInstance).length;
|
||||||
if (!hasNewChanges) return;
|
if (!hasNewChanges) return;
|
||||||
|
|
|
@ -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}}*",
|
"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}})",
|
"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",
|
"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"
|
||||||
}
|
}
|
|
@ -167,8 +167,8 @@
|
||||||
"Action not allowed on the test environment": "Esta acción no está permitida en el entorno de pruebas",
|
"Action not allowed on the test environment": "Esta acción no está permitida en el entorno de pruebas",
|
||||||
"The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta",
|
"The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta",
|
||||||
"Sorts whole route": "Reordena ruta entera",
|
"Sorts whole route": "Reordena ruta entera",
|
||||||
"New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día <strong>{{shipped}}</strong>, con una cantidad de <strong>{{quantity}}</strong> y un precio de <strong>{{price}} €</strong>",
|
"New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}* y un precio de *{{price}} €*",
|
||||||
"New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día <strong>{{shipped}}</strong>, con una cantidad de <strong>{{quantity}}</strong>",
|
"New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}*",
|
||||||
"Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío",
|
"Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío",
|
||||||
"This BIC already exist.": "Este BIC ya existe.",
|
"This BIC already exist.": "Este BIC ya existe.",
|
||||||
"That item doesn't exists": "Ese artículo no existe",
|
"That item doesn't exists": "Ese artículo no existe",
|
||||||
|
@ -176,5 +176,7 @@
|
||||||
"Invalid account": "Cuenta inválida",
|
"Invalid account": "Cuenta inválida",
|
||||||
"Compensation account is empty": "La cuenta para compensar está vacia",
|
"Compensation account is empty": "La cuenta para compensar está vacia",
|
||||||
"This genus already exist": "Este genus ya existe",
|
"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"
|
||||||
}
|
}
|
|
@ -227,36 +227,6 @@ module.exports = Self => {
|
||||||
await Self.app.models.ClientCredit.create(newCredit);
|
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 => {
|
Self.observe('after save', async ctx => {
|
||||||
if (ctx.isNewInstance) return;
|
if (ctx.isNewInstance) return;
|
||||||
|
@ -303,8 +273,58 @@ module.exports = Self => {
|
||||||
query: params
|
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) {
|
async function validateCreditChange(ctx, finalState) {
|
||||||
let models = Self.app.models;
|
let models = Self.app.models;
|
||||||
let userId = ctx.options.accessToken.userId;
|
let userId = ctx.options.accessToken.userId;
|
||||||
|
@ -341,4 +361,34 @@ module.exports = Self => {
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
throw new UserError('The role cannot set this credit amount');
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -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`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="vn-mx-xs" v-if="attachment.component">
|
<div class="vn-mx-xs" v-if="attachment.component">
|
||||||
<a target="_blank" class="vn-py-sm vn-px-md" v-bind:href="path">
|
<a target="_blank" class="vn-py-sm vn-px-md" v-bind:href="attachmentPath">
|
||||||
<div class="text">{{attachment.filename}}</div>
|
<div class="text">{{attachment.filename}}</div>
|
||||||
<div class="icon vn-pl-md">▼</div>
|
<div class="icon vn-pl-md">▼</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'attachment',
|
name: 'attachment',
|
||||||
computed: {
|
computed: {
|
||||||
path() {
|
attachmentPath() {
|
||||||
const filename = this.attachment.filename;
|
const filename = this.attachment.filename;
|
||||||
const component = this.attachment.component;
|
const component = this.attachment.component;
|
||||||
if (this.attachment.cid)
|
if (this.attachment.cid)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
subject: Avis initial de solde débiteur
|
||||||
|
title: Avis initial de solde débiteur
|
||||||
|
sections:
|
||||||
|
introduction:
|
||||||
|
title: Madame, Monsieur,
|
||||||
|
description: Sauf erreur ou omission de notre part, nous constatons que votre
|
||||||
|
compte client présente à ce jour un solde débiteur.
|
||||||
|
checkExtract: Ce montant correspond à nos factures restées impayées, ci-joint en annexe.
|
||||||
|
Notre service administratif se fera un plaisir de clarifier toutes les questions que vous
|
||||||
|
pourriez avoir, et vous fournira également tout document que vous nous demandez.
|
||||||
|
checkValidData: Si lors de la vérification des données fournies, elles sont correctes et
|
||||||
|
l’échéance étant dépassée, nous vous demandons de bien vouloir régulariser cette situation.
|
||||||
|
payMethod: Si vous ne souhaitez pas vous rendre personnellement à nos bureaux, vous
|
||||||
|
pouvez effectuer le paiement par virement bancaire sur le compte qui apparaît en
|
||||||
|
bas du relevé, en indiquant votre numéro de client, ou vous pouvez effectuer le
|
||||||
|
paiement en ligne avec une carte bleue sur notre site Internet.
|
||||||
|
conclusion: Dans le cas où votre règlement aurait été adressé entre temps,
|
||||||
|
nous vous prions de ne pas tenir compte de la présente.
|
||||||
|
Nous vous remercions par avance de votre aimable coopération.
|
||||||
|
transferAccount: Coordonées pour virement bancaire
|
|
@ -0,0 +1,10 @@
|
||||||
|
title: Relevé de compte
|
||||||
|
claimId: Réclamation
|
||||||
|
clientId: Client
|
||||||
|
clientData: Données client
|
||||||
|
date: Date
|
||||||
|
concept: Objet
|
||||||
|
invoiced: Facturé
|
||||||
|
payed: Payé
|
||||||
|
balance: Solde
|
||||||
|
client: Client {0}
|
Loading…
Reference in New Issue