Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5327-ticket.sale_ordenarPorColumnas
gitea/salix/pipeline/head Build queued...
Details
gitea/salix/pipeline/head Build queued...
Details
This commit is contained in:
commit
f00643505d
|
@ -6,5 +6,9 @@
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": true
|
||||||
},
|
},
|
||||||
"search.useIgnoreFiles": false,
|
"search.useIgnoreFiles": false,
|
||||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||||
|
"eslint.format.enable": true,
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
40
CHANGELOG.md
40
CHANGELOG.md
|
@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [2312.01] - 2023-04-06
|
## [2320.01] - 2023-05-25
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
-
|
-
|
||||||
|
@ -16,6 +16,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Fixed
|
### Fixed
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2318.01] - 2023-05-08
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- (Usuarios -> Histórico) Nueva sección
|
||||||
|
- (Roles -> Histórico) Nueva sección
|
||||||
|
- (General -> Traducciones) Correo de bienvenida a clientes al portugués y al francés
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- (Ticket -> Boxing) Arreglado selección de horas
|
||||||
|
- (Cesta -> Índice) Optimizada búsqueda
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2314.01] - 2023-04-20
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- (Clientes -> Morosos) Ahora se puede filtrar por las columnas "Desde" y "Fecha Ú. O.". También se envia un email al comercial cuando se añade una nota.
|
||||||
|
- (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia
|
||||||
|
- (Facturas recibidas -> Bases negativas) Nueva sección
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- (Clientes -> Morosos) Ahora se mantienen los elementos seleccionados al hacer sroll.
|
||||||
|
|
||||||
|
## [2312.01] - 2023-04-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- (Monitor tickets) Cuando se filtra por 'Pendiente' ya no muestra los estados de 'Previa'
|
||||||
|
- (Envíos -> Extra comunitarios) Se agrupan las entradas del mismo travel. Añadidos campos Referencia y Importe.
|
||||||
|
- (Envíos -> Índice) Cambiado el buscador superior por uno lateral
|
||||||
|
|
||||||
## [2310.01] - 2023-03-23
|
## [2310.01] - 2023-03-23
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -52,6 +52,7 @@ pipeline {
|
||||||
}}}
|
}}}
|
||||||
environment {
|
environment {
|
||||||
NODE_ENV = ""
|
NODE_ENV = ""
|
||||||
|
TZ = 'Europe/Madrid'
|
||||||
}
|
}
|
||||||
parallel {
|
parallel {
|
||||||
stage('Frontend') {
|
stage('Frontend') {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: account
|
||||||
|
columns:
|
||||||
|
id: id
|
||||||
|
name: name
|
||||||
|
roleFk: role
|
||||||
|
nickname: nickname
|
||||||
|
lang: lang
|
||||||
|
password: password
|
||||||
|
bcryptPassword: bcrypt password
|
||||||
|
active: active
|
||||||
|
email: email
|
||||||
|
emailVerified: email verified
|
||||||
|
created: created
|
||||||
|
updated: updated
|
||||||
|
image: image
|
||||||
|
hasGrant: has grant
|
||||||
|
userFk: user
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: cuenta
|
||||||
|
columns:
|
||||||
|
id: id
|
||||||
|
name: nombre
|
||||||
|
roleFk: rol
|
||||||
|
nickname: apodo
|
||||||
|
lang: idioma
|
||||||
|
password: contraseña
|
||||||
|
bcryptPassword: contraseña bcrypt
|
||||||
|
active: activo
|
||||||
|
email: email
|
||||||
|
emailVerified: email verificado
|
||||||
|
created: creado
|
||||||
|
updated: actualizado
|
||||||
|
image: imagen
|
||||||
|
hasGrant: tiene permiso
|
||||||
|
userFk: usuario
|
|
@ -1,9 +1,9 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('campaign latest()', () => {
|
describe('campaign latest()', () => {
|
||||||
it('should return the campaigns from the last year', async() => {
|
it('should return the campaigns from the last year', async() => {
|
||||||
const now = Date.vnNew();
|
const now = Date.vnNew();
|
||||||
const result = await app.models.Campaign.latest();
|
const result = await models.Campaign.latest();
|
||||||
const randomIndex = Math.floor(Math.random() * result.length);
|
const randomIndex = Math.floor(Math.random() * result.length);
|
||||||
const campaignDated = result[randomIndex].dated;
|
const campaignDated = result[randomIndex].dated;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ describe('campaign latest()', () => {
|
||||||
it('should return the campaigns from the current year', async() => {
|
it('should return the campaigns from the current year', async() => {
|
||||||
const now = Date.vnNew();
|
const now = Date.vnNew();
|
||||||
const currentYear = now.getFullYear();
|
const currentYear = now.getFullYear();
|
||||||
const result = await app.models.Campaign.latest({
|
const result = await models.Campaign.latest({
|
||||||
where: {dated: {like: `%${currentYear}%`}}
|
where: {dated: {like: `%${currentYear}%`}}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('campaign upcoming()', () => {
|
describe('campaign upcoming()', () => {
|
||||||
it('should return the upcoming campaign but from the last year', async() => {
|
it('should return the upcoming campaign but from the last year', async() => {
|
||||||
const response = await app.models.Campaign.upcoming();
|
const response = await models.Campaign.upcoming();
|
||||||
const campaignDated = response.dated;
|
const campaignDated = response.dated;
|
||||||
const now = Date.vnNew();
|
const now = Date.vnNew();
|
||||||
|
|
||||||
|
|
|
@ -26,20 +26,27 @@ module.exports = Self => {
|
||||||
Self.send = async(ctx, to, message) => {
|
Self.send = async(ctx, to, message) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const accessToken = ctx.req.accessToken;
|
const accessToken = ctx.req.accessToken;
|
||||||
const sender = await models.Account.findById(accessToken.userId);
|
const sender = await models.VnUser.findById(accessToken.userId);
|
||||||
const recipient = to.replace('@', '');
|
const recipient = to.replace('@', '');
|
||||||
|
|
||||||
if (sender.name != recipient) {
|
if (sender.name != recipient) {
|
||||||
await models.Chat.create({
|
const chat = await models.Chat.create({
|
||||||
senderFk: sender.id,
|
senderFk: sender.id,
|
||||||
recipient: to,
|
recipient: to,
|
||||||
dated: Date.vnNew(),
|
dated: Date.vnNew(),
|
||||||
checkUserStatus: 0,
|
checkUserStatus: 0,
|
||||||
message: message,
|
message: message,
|
||||||
status: 0,
|
status: 'sending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
|
||||||
|
await Self.updateChat(chat, 'sent');
|
||||||
|
} catch (error) {
|
||||||
|
await Self.updateChat(chat, 'error', error);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.sendCheckingPresence = async(ctx, recipientId, message, options) => {
|
Self.sendCheckingPresence = async(ctx, recipientId, message) => {
|
||||||
if (!recipientId) return false;
|
if (!recipientId) return false;
|
||||||
|
|
||||||
const myOptions = {};
|
|
||||||
|
|
||||||
if (typeof options == 'object')
|
|
||||||
Object.assign(myOptions, options);
|
|
||||||
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const sender = await models.Account.findById(userId);
|
const sender = await models.VnUser.findById(userId, {fields: ['id']});
|
||||||
const recipient = await models.Account.findById(recipientId, null, myOptions);
|
const recipient = await models.VnUser.findById(recipientId, null);
|
||||||
|
|
||||||
// Prevent sending messages to yourself
|
// Prevent sending messages to yourself
|
||||||
if (recipientId == userId) return false;
|
if (recipientId == userId) return false;
|
||||||
|
@ -46,16 +41,23 @@ module.exports = Self => {
|
||||||
if (process.env.NODE_ENV == 'test')
|
if (process.env.NODE_ENV == 'test')
|
||||||
message = `[Test:Environment to user ${userId}] ` + message;
|
message = `[Test:Environment to user ${userId}] ` + message;
|
||||||
|
|
||||||
await models.Chat.create({
|
const chat = await models.Chat.create({
|
||||||
senderFk: sender.id,
|
senderFk: sender.id,
|
||||||
recipient: `@${recipient.name}`,
|
recipient: `@${recipient.name}`,
|
||||||
dated: Date.vnNew(),
|
dated: Date.vnNew(),
|
||||||
checkUserStatus: 1,
|
checkUserStatus: 1,
|
||||||
message: message,
|
message: message,
|
||||||
status: 0,
|
status: 'sending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Self.sendCheckingUserStatus(chat);
|
||||||
|
await Self.updateChat(chat, 'sent');
|
||||||
|
} catch (error) {
|
||||||
|
await Self.updateChat(chat, 'error', error);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,6 @@ module.exports = Self => {
|
||||||
Self.remoteMethodCtx('sendQueued', {
|
Self.remoteMethodCtx('sendQueued', {
|
||||||
description: 'Send a RocketChat message',
|
description: 'Send a RocketChat message',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [],
|
|
||||||
returns: {
|
returns: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
|
@ -16,14 +15,17 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.sendQueued = async() => {
|
Self.sendQueued = async() => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const maxAttempts = 3;
|
|
||||||
const sentStatus = 1;
|
|
||||||
const errorStatus = 2;
|
|
||||||
|
|
||||||
const chats = await models.Chat.find({
|
const chats = await models.Chat.find({
|
||||||
where: {
|
where: {
|
||||||
status: {neq: sentStatus},
|
status: {
|
||||||
attempts: {lt: maxAttempts}
|
nin: [
|
||||||
|
'sent',
|
||||||
|
'sending'
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
attempts: {lt: 3}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,16 +33,16 @@ module.exports = Self => {
|
||||||
if (chat.checkUserStatus) {
|
if (chat.checkUserStatus) {
|
||||||
try {
|
try {
|
||||||
await Self.sendCheckingUserStatus(chat);
|
await Self.sendCheckingUserStatus(chat);
|
||||||
await updateChat(chat, sentStatus);
|
await Self.updateChat(chat, 'sent');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await updateChat(chat, errorStatus, error);
|
await Self.updateChat(chat, 'error', error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
|
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
|
||||||
await updateChat(chat, sentStatus);
|
await Self.updateChat(chat, 'sent');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await updateChat(chat, errorStatus, error);
|
await Self.updateChat(chat, 'error', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,7 @@ module.exports = Self => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
|
||||||
const recipientName = chat.recipient.slice(1);
|
const recipientName = chat.recipient.slice(1);
|
||||||
const recipient = await models.Account.findOne({
|
const recipient = await models.VnUser.findOne({
|
||||||
where: {
|
where: {
|
||||||
name: recipientName
|
name: recipientName
|
||||||
}
|
}
|
||||||
|
@ -102,7 +104,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const sender = await models.Account.findById(senderFk);
|
const sender = await models.VnUser.findById(senderFk);
|
||||||
|
|
||||||
const login = await Self.getServiceAuth();
|
const login = await Self.getServiceAuth();
|
||||||
const avatar = `${login.host}/avatar/${sender.name}`;
|
const avatar = `${login.host}/avatar/${sender.name}`;
|
||||||
|
@ -128,15 +130,17 @@ module.exports = Self => {
|
||||||
* @param {object} chat - The chat
|
* @param {object} chat - The chat
|
||||||
* @param {string} status - The new status
|
* @param {string} status - The new status
|
||||||
* @param {string} error - The error
|
* @param {string} error - The error
|
||||||
|
* @param {object} options - Query options
|
||||||
* @return {Promise} - The request promise
|
* @return {Promise} - The request promise
|
||||||
*/
|
*/
|
||||||
async function updateChat(chat, status, error) {
|
|
||||||
|
Self.updateChat = async(chat, status, error) => {
|
||||||
return chat.updateAttributes({
|
return chat.updateAttributes({
|
||||||
status: status,
|
status: status,
|
||||||
attempts: ++chat.attempts,
|
attempts: ++chat.attempts,
|
||||||
error: error
|
error: error
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current user status on Rocketchat
|
* Returns the current user status on Rocketchat
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('Chat notifyIssue()', () => {
|
describe('Chat notifyIssue()', () => {
|
||||||
const ctx = {req: {accessToken: {userId: 1}}};
|
const ctx = {req: {accessToken: {userId: 1}}};
|
||||||
ctx.req.__ = value => {
|
ctx.req.__ = value => {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
const chatModel = app.models.Chat;
|
const chatModel = models.Chat;
|
||||||
const osTicketModel = app.models.OsTicket;
|
const osTicketModel = models.OsTicket;
|
||||||
const departmentId = 31;
|
const departmentId = 31;
|
||||||
|
|
||||||
it(`should not call to the send() method and neither return a response`, async() => {
|
it(`should not call to the send() method and neither return a response`, async() => {
|
||||||
|
@ -29,7 +29,7 @@ describe('Chat notifyIssue()', () => {
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
const expectedMessage = `@all ➔ There's a new urgent ticket:\r\n[ID: 00001 - Issue title @batman](https://cau.verdnatura.es/scp/tickets.php?id=1)`;
|
const expectedMessage = `@all ➔ There's a new urgent ticket:\r\n[ID: 00001 - Issue title @batman](https://cau.verdnatura.es/scp/tickets.php?id=1)`;
|
||||||
|
|
||||||
const department = await app.models.Department.findById(departmentId);
|
const department = await models.Department.findById(departmentId);
|
||||||
let orgChatName = department.chatName;
|
let orgChatName = department.chatName;
|
||||||
await department.updateAttribute('chatName', 'IT');
|
await department.updateAttribute('chatName', 'IT');
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('Chat send()', () => {
|
describe('Chat send()', () => {
|
||||||
it('should return true as response', async() => {
|
it('should return true as response', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 1}}};
|
let ctx = {req: {accessToken: {userId: 1}}};
|
||||||
let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something');
|
let response = await models.Chat.send(ctx, '@salesPerson', 'I changed something');
|
||||||
|
|
||||||
expect(response).toEqual(true);
|
expect(response).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false as response', async() => {
|
it('should return false as response', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 18}}};
|
let ctx = {req: {accessToken: {userId: 18}}};
|
||||||
let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something');
|
let response = await models.Chat.send(ctx, '@salesPerson', 'I changed something');
|
||||||
|
|
||||||
expect(response).toEqual(false);
|
expect(response).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,7 @@ describe('Chat sendCheckingPresence()', () => {
|
||||||
|
|
||||||
const chat = {
|
const chat = {
|
||||||
checkUserStatus: 1,
|
checkUserStatus: 1,
|
||||||
status: 0,
|
status: 'pending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ describe('Chat sendCheckingPresence()', () => {
|
||||||
|
|
||||||
const chat = {
|
const chat = {
|
||||||
checkUserStatus: 0,
|
checkUserStatus: 0,
|
||||||
status: 0,
|
status: 'pending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,7 @@ module.exports = Self => {
|
||||||
try {
|
try {
|
||||||
const sale = await models.Sale.findById(saleId, null, myOptions);
|
const sale = await models.Sale.findById(saleId, null, myOptions);
|
||||||
const saleUpdated = await sale.updateAttributes({
|
const saleUpdated = await sale.updateAttributes({
|
||||||
originalQuantity: sale.quantity,
|
quantity
|
||||||
quantity: quantity
|
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('getSectors()', () => {
|
describe('getSectors()', () => {
|
||||||
it('return list of sectors', async() => {
|
it('return list of sectors', async() => {
|
||||||
let response = await app.models.Collection.getSectors();
|
let response = await models.Collection.getSectors();
|
||||||
|
|
||||||
expect(response.length).toBeGreaterThan(0);
|
expect(response.length).toBeGreaterThan(0);
|
||||||
expect(response[0].id).toEqual(1);
|
expect(response[0].id).toEqual(1);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('newCollection()', () => {
|
describe('newCollection()', () => {
|
||||||
it('should return a new collection', async() => {
|
it('should return a new collection', async() => {
|
||||||
pending('#3400 analizar que hacer con rutas de back collection');
|
pending('#3400 analizar que hacer con rutas de back collection');
|
||||||
let ctx = {req: {accessToken: {userId: 1106}}};
|
let ctx = {req: {accessToken: {userId: 1106}}};
|
||||||
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1);
|
let response = await models.Collection.newCollection(ctx, 1, 1, 1);
|
||||||
|
|
||||||
expect(response.length).toBeGreaterThan(0);
|
expect(response.length).toBeGreaterThan(0);
|
||||||
expect(response[0].ticketFk).toEqual(2);
|
expect(response[0].ticketFk).toEqual(2);
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('setSaleQuantity()', () => {
|
describe('setSaleQuantity()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should change quantity sale', async() => {
|
it('should change quantity sale', async() => {
|
||||||
const tx = await models.Ticket.beginTransaction({});
|
const tx = await models.Ticket.beginTransaction({});
|
||||||
|
|
||||||
|
@ -15,7 +30,7 @@ describe('setSaleQuantity()', () => {
|
||||||
await models.Collection.setSaleQuantity(saleId, newQuantity, options);
|
await models.Collection.setSaleQuantity(saleId, newQuantity, options);
|
||||||
const updateSale = await models.Sale.findById(saleId, null, options);
|
const updateSale = await models.Sale.findById(saleId, null, options);
|
||||||
|
|
||||||
expect(updateSale.originalQuantity).toEqual(originalSale.quantity);
|
expect(updateSale.quantity).not.toEqual(originalSale.quantity);
|
||||||
expect(updateSale.quantity).toEqual(newQuantity);
|
expect(updateSale.quantity).toEqual(newQuantity);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('dms downloadFile()', () => {
|
describe('dms downloadFile()', () => {
|
||||||
let dmsId = 1;
|
let dmsId = 1;
|
||||||
|
@ -6,7 +6,7 @@ describe('dms downloadFile()', () => {
|
||||||
it('should return a response for an employee with text content-type', async() => {
|
it('should return a response for an employee with text content-type', async() => {
|
||||||
let workerId = 1107;
|
let workerId = 1107;
|
||||||
let ctx = {req: {accessToken: {userId: workerId}}};
|
let ctx = {req: {accessToken: {userId: workerId}}};
|
||||||
const result = await app.models.Dms.downloadFile(ctx, dmsId);
|
const result = await models.Dms.downloadFile(ctx, dmsId);
|
||||||
|
|
||||||
expect(result[1]).toEqual('text/plain');
|
expect(result[1]).toEqual('text/plain');
|
||||||
});
|
});
|
||||||
|
@ -16,7 +16,7 @@ describe('dms downloadFile()', () => {
|
||||||
let ctx = {req: {accessToken: {userId: clientId}}};
|
let ctx = {req: {accessToken: {userId: clientId}}};
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
await app.models.Dms.downloadFile(ctx, dmsId).catch(e => {
|
await models.Dms.downloadFile(ctx, dmsId).catch(e => {
|
||||||
error = e;
|
error = e;
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
expect(error.message).toEqual(`You don't have enough privileges`);
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('dms removeFile()', () => {
|
describe('dms removeFile()', () => {
|
||||||
let dmsId = 1;
|
let dmsId = 1;
|
||||||
|
@ -8,7 +8,7 @@ describe('dms removeFile()', () => {
|
||||||
let ctx = {req: {accessToken: {userId: clientId}}};
|
let ctx = {req: {accessToken: {userId: clientId}}};
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
await app.models.Dms.removeFile(ctx, dmsId).catch(e => {
|
await models.Dms.removeFile(ctx, dmsId).catch(e => {
|
||||||
error = e;
|
error = e;
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
expect(error.message).toEqual(`You don't have enough privileges`);
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('dms updateFile()', () => {
|
describe('dms updateFile()', () => {
|
||||||
it(`should return an error for a user without enough privileges`, async() => {
|
it(`should return an error for a user without enough privileges`, async() => {
|
||||||
|
@ -11,7 +11,7 @@ describe('dms updateFile()', () => {
|
||||||
let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: dmsTypeId}};
|
let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: dmsTypeId}};
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
await app.models.Dms.updateFile(ctx, dmsId, warehouseId, companyId, dmsTypeId).catch(e => {
|
await models.Dms.updateFile(ctx, dmsId, warehouseId, companyId, dmsTypeId).catch(e => {
|
||||||
error = e;
|
error = e;
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
expect(error.message).toEqual(`You don't have enough privileges`);
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('dms uploadFile()', () => {
|
describe('dms uploadFile()', () => {
|
||||||
it(`should return an error for a user without enough privileges`, async() => {
|
it(`should return an error for a user without enough privileges`, async() => {
|
||||||
|
@ -7,7 +7,7 @@ describe('dms uploadFile()', () => {
|
||||||
let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: ticketDmsTypeId}};
|
let ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: ticketDmsTypeId}};
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
await app.models.Dms.uploadFile(ctx).catch(e => {
|
await models.Dms.uploadFile(ctx).catch(e => {
|
||||||
error = e;
|
error = e;
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
expect(error.message).toEqual(`You don't have enough privileges`);
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const path = require('path');
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('scrub', {
|
||||||
|
description: 'Deletes images without database reference',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'collection',
|
||||||
|
type: 'string',
|
||||||
|
description: 'The collection name',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'remove',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Delete instead of move images to trash'
|
||||||
|
}, {
|
||||||
|
arg: 'limit',
|
||||||
|
type: 'integer',
|
||||||
|
description: 'Maximum number of images to clean'
|
||||||
|
}, {
|
||||||
|
arg: 'dryRun',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Simulate actions'
|
||||||
|
}, {
|
||||||
|
arg: 'skipLock',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Wether to skip exclusive lock'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'integer',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/scrub`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.scrub = async function(collection, remove, limit, dryRun, skipLock) {
|
||||||
|
const $ = Self.app.models;
|
||||||
|
|
||||||
|
const env = process.env.NODE_ENV;
|
||||||
|
dryRun = dryRun || (env && env !== 'production');
|
||||||
|
|
||||||
|
const instance = await $.ImageCollection.findOne({
|
||||||
|
fields: ['id'],
|
||||||
|
where: {name: collection}
|
||||||
|
});
|
||||||
|
if (!instance)
|
||||||
|
throw new UserError('Collection does not exist');
|
||||||
|
|
||||||
|
const container = await $.ImageContainer.container(collection);
|
||||||
|
const rootPath = container.client.root;
|
||||||
|
|
||||||
|
let tx;
|
||||||
|
let opts;
|
||||||
|
const lockName = 'salix.Image.scrub';
|
||||||
|
|
||||||
|
if (!skipLock) {
|
||||||
|
tx = await Self.beginTransaction({timeout: null});
|
||||||
|
opts = {transaction: tx};
|
||||||
|
|
||||||
|
const [row] = await Self.rawSql(
|
||||||
|
`SELECT GET_LOCK(?, 10) hasLock`, [lockName], opts);
|
||||||
|
if (!row.hasLock)
|
||||||
|
throw new UserError('Cannot obtain exclusive lock');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const now = Date.vnNew().toJSON();
|
||||||
|
const scrubDir = path.join(rootPath, '.scrub', now);
|
||||||
|
|
||||||
|
const collectionDir = path.join(rootPath, collection);
|
||||||
|
const sizes = await fs.readdir(collectionDir);
|
||||||
|
let cleanCount = 0;
|
||||||
|
|
||||||
|
mainLoop: for (const size of sizes) {
|
||||||
|
const sizeDir = path.join(collectionDir, size);
|
||||||
|
const scrubSizeDir = path.join(scrubDir, collection, size);
|
||||||
|
const images = await fs.readdir(sizeDir);
|
||||||
|
for (const image of images) {
|
||||||
|
const imageName = path.parse(image).name;
|
||||||
|
const count = await Self.count({
|
||||||
|
collectionFk: collection,
|
||||||
|
name: imageName
|
||||||
|
}, opts);
|
||||||
|
const exists = count > 0;
|
||||||
|
let scrubDirCreated = false;
|
||||||
|
if (!exists) {
|
||||||
|
const srcFile = path.join(sizeDir, image);
|
||||||
|
if (remove !== true) {
|
||||||
|
if (!scrubDirCreated) {
|
||||||
|
if (!dryRun)
|
||||||
|
await fs.mkdir(scrubSizeDir, {recursive: true});
|
||||||
|
scrubDirCreated = true;
|
||||||
|
}
|
||||||
|
const dstFile = path.join(scrubSizeDir, image);
|
||||||
|
if (!dryRun) await fs.rename(srcFile, dstFile);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (!dryRun) await fs.unlink(srcFile);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanCount++;
|
||||||
|
if (limit && cleanCount == limit)
|
||||||
|
break mainLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleanCount;
|
||||||
|
} finally {
|
||||||
|
if (!skipLock) {
|
||||||
|
try {
|
||||||
|
await Self.rawSql(`DO RELEASE_LOCK(?)`, [lockName], opts);
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('image download()', () => {
|
describe('image download()', () => {
|
||||||
const collection = 'user';
|
const collection = 'user';
|
||||||
|
@ -8,7 +8,7 @@ describe('image download()', () => {
|
||||||
|
|
||||||
it('should return the image content-type of the user', async() => {
|
it('should return the image content-type of the user', async() => {
|
||||||
const userId = 9;
|
const userId = 9;
|
||||||
const image = await app.models.Image.download(ctx, collection, size, userId);
|
const image = await models.Image.download(ctx, collection, size, userId);
|
||||||
const contentType = image[1];
|
const contentType = image[1];
|
||||||
|
|
||||||
expect(contentType).toEqual('image/png');
|
expect(contentType).toEqual('image/png');
|
||||||
|
@ -16,7 +16,7 @@ describe('image download()', () => {
|
||||||
|
|
||||||
it(`should return false if the user doesn't have image`, async() => {
|
it(`should return false if the user doesn't have image`, async() => {
|
||||||
const userId = 1110;
|
const userId = 1110;
|
||||||
const image = await app.models.Image.download(ctx, collection, size, userId);
|
const image = await models.Image.download(ctx, collection, size, userId);
|
||||||
|
|
||||||
expect(image).toBeFalse();
|
expect(image).toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('image upload()', () => {
|
describe('image upload()', () => {
|
||||||
describe('as buyer', () => {
|
describe('as buyer', () => {
|
||||||
|
@ -16,7 +16,7 @@ describe('image upload()', () => {
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
try {
|
try {
|
||||||
await app.models.Image.upload(ctx);
|
await models.Image.upload(ctx);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = err;
|
error = err;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ describe('image upload()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call to the TempContainer upload method for the collection "catalog"', async() => {
|
it('should call to the TempContainer upload method for the collection "catalog"', async() => {
|
||||||
const containerModel = app.models.TempContainer;
|
const containerModel = models.TempContainer;
|
||||||
spyOn(containerModel, 'upload');
|
spyOn(containerModel, 'upload');
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: buyerId}},
|
const ctx = {req: {accessToken: {userId: buyerId}},
|
||||||
|
@ -36,7 +36,7 @@ describe('image upload()', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.Image.upload(ctx);
|
await models.Image.upload(ctx);
|
||||||
} catch (err) { }
|
} catch (err) { }
|
||||||
|
|
||||||
expect(containerModel.upload).toHaveBeenCalled();
|
expect(containerModel.upload).toHaveBeenCalled();
|
||||||
|
@ -49,7 +49,7 @@ describe('image upload()', () => {
|
||||||
const itemId = 4;
|
const itemId = 4;
|
||||||
|
|
||||||
it('should be able to call to the TempContainer upload method for the collection "user"', async() => {
|
it('should be able to call to the TempContainer upload method for the collection "user"', async() => {
|
||||||
const containerModel = app.models.TempContainer;
|
const containerModel = models.TempContainer;
|
||||||
spyOn(containerModel, 'upload');
|
spyOn(containerModel, 'upload');
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: marketingId}},
|
const ctx = {req: {accessToken: {userId: marketingId}},
|
||||||
|
@ -60,14 +60,14 @@ describe('image upload()', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.Image.upload(ctx);
|
await models.Image.upload(ctx);
|
||||||
} catch (err) { }
|
} catch (err) { }
|
||||||
|
|
||||||
expect(containerModel.upload).toHaveBeenCalled();
|
expect(containerModel.upload).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to call to the TempContainer upload method for the collection "catalog"', async() => {
|
it('should be able to call to the TempContainer upload method for the collection "catalog"', async() => {
|
||||||
const containerModel = app.models.TempContainer;
|
const containerModel = models.TempContainer;
|
||||||
spyOn(containerModel, 'upload');
|
spyOn(containerModel, 'upload');
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: marketingId}},
|
const ctx = {req: {accessToken: {userId: marketingId}},
|
||||||
|
@ -78,7 +78,7 @@ describe('image upload()', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.Image.upload(ctx);
|
await models.Image.upload(ctx);
|
||||||
} catch (err) { }
|
} catch (err) { }
|
||||||
|
|
||||||
expect(containerModel.upload).toHaveBeenCalled();
|
expect(containerModel.upload).toHaveBeenCalled();
|
||||||
|
@ -91,7 +91,7 @@ describe('image upload()', () => {
|
||||||
const itemId = 4;
|
const itemId = 4;
|
||||||
|
|
||||||
it('should upload a file for the collection "user" and call to the TempContainer upload method', async() => {
|
it('should upload a file for the collection "user" and call to the TempContainer upload method', async() => {
|
||||||
const containerModel = app.models.TempContainer;
|
const containerModel = models.TempContainer;
|
||||||
spyOn(containerModel, 'upload');
|
spyOn(containerModel, 'upload');
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: hhrrId}},
|
const ctx = {req: {accessToken: {userId: hhrrId}},
|
||||||
|
@ -102,7 +102,7 @@ describe('image upload()', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.Image.upload(ctx);
|
await models.Image.upload(ctx);
|
||||||
} catch (err) { }
|
} catch (err) { }
|
||||||
|
|
||||||
expect(containerModel.upload).toHaveBeenCalled();
|
expect(containerModel.upload).toHaveBeenCalled();
|
||||||
|
@ -118,7 +118,7 @@ describe('image upload()', () => {
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
try {
|
try {
|
||||||
await app.models.Image.upload(ctx);
|
await models.Image.upload(ctx);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = err;
|
error = err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs/promises');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const uuid = require('uuid');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('upload', {
|
Self.remoteMethodCtx('upload', {
|
||||||
|
@ -13,13 +12,13 @@ module.exports = Self => {
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
description: 'The entity id',
|
description: 'The entity id',
|
||||||
required: true
|
required: true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
arg: 'collection',
|
arg: 'collection',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'The collection name',
|
description: 'The collection name',
|
||||||
required: true
|
required: true
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'Object',
|
type: 'Object',
|
||||||
root: true
|
root: true
|
||||||
|
@ -36,7 +35,7 @@ module.exports = Self => {
|
||||||
const fileOptions = {};
|
const fileOptions = {};
|
||||||
const args = ctx.args;
|
const args = ctx.args;
|
||||||
|
|
||||||
let srcFile;
|
let tempFilePath;
|
||||||
try {
|
try {
|
||||||
const hasWriteRole = await models.ImageCollection.hasWriteRole(ctx, args.collection);
|
const hasWriteRole = await models.ImageCollection.hasWriteRole(ctx, args.collection);
|
||||||
if (!hasWriteRole)
|
if (!hasWriteRole)
|
||||||
|
@ -53,15 +52,20 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name);
|
const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name);
|
||||||
srcFile = path.join(file.client.root, file.container, file.name);
|
tempFilePath = path.join(file.client.root, file.container, file.name);
|
||||||
|
|
||||||
const fileName = `${uuid.v4()}.png`;
|
const fileName = `${args.id}.png`;
|
||||||
await models.Image.registerImage(args.collection, srcFile, fileName, args.id);
|
|
||||||
} catch (e) {
|
|
||||||
if (fs.existsSync(srcFile))
|
|
||||||
await fs.unlink(srcFile);
|
|
||||||
|
|
||||||
throw e;
|
await models.Image.resize({
|
||||||
|
collectionName: args.collection,
|
||||||
|
srcFile: tempFilePath,
|
||||||
|
fileName: fileName,
|
||||||
|
entityId: args.id
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
await fs.unlink(tempFilePath);
|
||||||
|
} catch (error) { }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -69,15 +69,15 @@ module.exports = Self => {
|
||||||
|
|
||||||
const result = response.headers.get('set-cookie');
|
const result = response.headers.get('set-cookie');
|
||||||
const [firtHeader] = result.split(' ');
|
const [firtHeader] = result.split(' ');
|
||||||
const firtCookie = firtHeader.substring(0, firtHeader.length - 1);
|
const cookie = firtHeader.substring(0, firtHeader.length - 1);
|
||||||
const body = await response.text();
|
const body = await response.text();
|
||||||
const dom = new jsdom.JSDOM(body);
|
const dom = new jsdom.JSDOM(body);
|
||||||
const token = dom.window.document.querySelector('[name="__CSRFToken__"]').value;
|
const token = dom.window.document.querySelector('[name="__CSRFToken__"]').value;
|
||||||
|
|
||||||
await login(token, firtCookie);
|
await login(token, cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function login(token, firtCookie) {
|
async function login(token, cookie) {
|
||||||
const data = {
|
const data = {
|
||||||
__CSRFToken__: token,
|
__CSRFToken__: token,
|
||||||
do: 'scplogin',
|
do: 'scplogin',
|
||||||
|
@ -90,21 +90,18 @@ module.exports = Self => {
|
||||||
body: new URLSearchParams(data),
|
body: new URLSearchParams(data),
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
'Cookie': firtCookie
|
'Cookie': cookie
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const response = await fetch(ostUri, params);
|
await fetch(ostUri, params);
|
||||||
const result = response.headers.get('set-cookie');
|
|
||||||
const [firtHeader] = result.split(' ');
|
|
||||||
const secondCookie = firtHeader.substring(0, firtHeader.length - 1);
|
|
||||||
|
|
||||||
await close(token, secondCookie);
|
await close(token, cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function close(token, secondCookie) {
|
async function close(token, cookie) {
|
||||||
for (const ticketId of ticketsId) {
|
for (const ticketId of ticketsId) {
|
||||||
try {
|
try {
|
||||||
const lock = await getLockCode(token, secondCookie, ticketId);
|
const lock = await getLockCode(token, cookie, ticketId);
|
||||||
if (!lock.code) {
|
if (!lock.code) {
|
||||||
let error = `Can't get lock code`;
|
let error = `Can't get lock code`;
|
||||||
if (lock.msg) error += `: ${lock.msg}`;
|
if (lock.msg) error += `: ${lock.msg}`;
|
||||||
|
@ -127,7 +124,7 @@ module.exports = Self => {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: form,
|
body: form,
|
||||||
headers: {
|
headers: {
|
||||||
'Cookie': secondCookie
|
'Cookie': cookie
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
await fetch(ostUri, params);
|
await fetch(ostUri, params);
|
||||||
|
@ -139,13 +136,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getLockCode(token, secondCookie, ticketId) {
|
async function getLockCode(token, cookie, ticketId) {
|
||||||
const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`;
|
const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`;
|
||||||
const params = {
|
const params = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'X-CSRFToken': token,
|
'X-CSRFToken': token,
|
||||||
'Cookie': secondCookie
|
'Cookie': cookie
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const response = await fetch(ostUri, params);
|
const response = await fetch(ostUri, params);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('getStarredModules()', () => {
|
describe('getStarredModules()', () => {
|
||||||
|
@ -19,13 +19,13 @@ describe('getStarredModules()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should return the starred modules for a given user`, async() => {
|
it(`should return the starred modules for a given user`, async() => {
|
||||||
const newStarred = await app.models.StarredModule.create({workerFk: 9, moduleFk: 'customer', position: 1});
|
const newStarred = await models.StarredModule.create({workerFk: 9, moduleFk: 'customer', position: 1});
|
||||||
const starredModules = await app.models.StarredModule.getStarredModules(ctx);
|
const starredModules = await models.StarredModule.getStarredModules(ctx);
|
||||||
|
|
||||||
expect(starredModules.length).toEqual(1);
|
expect(starredModules.length).toEqual(1);
|
||||||
expect(starredModules[0].moduleFk).toEqual('customer');
|
expect(starredModules[0].moduleFk).toEqual('customer');
|
||||||
|
|
||||||
// restores
|
// restores
|
||||||
await app.models.StarredModule.destroyById(newStarred.id);
|
await models.StarredModule.destroyById(newStarred.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('setPosition()', () => {
|
describe('setPosition()', () => {
|
||||||
|
@ -21,7 +21,7 @@ describe('setPosition()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should increase the orders module position by replacing it with clients and vice versa', async() => {
|
it('should increase the orders module position by replacing it with clients and vice versa', async() => {
|
||||||
const tx = await app.models.StarredModule.beginTransaction({});
|
const tx = await models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {
|
where: {
|
||||||
|
@ -32,24 +32,24 @@ describe('setPosition()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
||||||
|
|
||||||
let orders = await app.models.StarredModule.findOne(filter, options);
|
let orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
let clients = await app.models.StarredModule.findOne(filter, options);
|
let clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(orders.position).toEqual(1);
|
expect(orders.position).toEqual(1);
|
||||||
expect(clients.position).toEqual(2);
|
expect(clients.position).toEqual(2);
|
||||||
|
|
||||||
await app.models.StarredModule.setPosition(ctx, 'customer', 'left', options);
|
await models.StarredModule.setPosition(ctx, 'customer', 'left', options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
clients = await app.models.StarredModule.findOne(filter, options);
|
clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'order';
|
filter.where.moduleFk = 'order';
|
||||||
orders = await app.models.StarredModule.findOne(filter, options);
|
orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(clients.position).toEqual(1);
|
expect(clients.position).toEqual(1);
|
||||||
expect(orders.position).toEqual(2);
|
expect(orders.position).toEqual(2);
|
||||||
|
@ -62,7 +62,7 @@ describe('setPosition()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decrease the orders module position by replacing it with clients and vice versa', async() => {
|
it('should decrease the orders module position by replacing it with clients and vice versa', async() => {
|
||||||
const tx = await app.models.StarredModule.beginTransaction({});
|
const tx = await models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {
|
where: {
|
||||||
|
@ -73,24 +73,24 @@ describe('setPosition()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
||||||
|
|
||||||
let orders = await app.models.StarredModule.findOne(filter, options);
|
let orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
let clients = await app.models.StarredModule.findOne(filter, options);
|
let clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(orders.position).toEqual(1);
|
expect(orders.position).toEqual(1);
|
||||||
expect(clients.position).toEqual(2);
|
expect(clients.position).toEqual(2);
|
||||||
|
|
||||||
await app.models.StarredModule.setPosition(ctx, 'order', 'right', options);
|
await models.StarredModule.setPosition(ctx, 'order', 'right', options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'order';
|
filter.where.moduleFk = 'order';
|
||||||
orders = await app.models.StarredModule.findOne(filter, options);
|
orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
clients = await app.models.StarredModule.findOne(filter, options);
|
clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(orders.position).toEqual(2);
|
expect(orders.position).toEqual(2);
|
||||||
expect(clients.position).toEqual(1);
|
expect(clients.position).toEqual(1);
|
||||||
|
@ -103,7 +103,7 @@ describe('setPosition()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should switch two modules after adding and deleting several modules', async() => {
|
it('should switch two modules after adding and deleting several modules', async() => {
|
||||||
const tx = await app.models.StarredModule.beginTransaction({});
|
const tx = await models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {
|
where: {
|
||||||
|
@ -115,29 +115,29 @@ describe('setPosition()', () => {
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'item', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'item', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'zone', options);
|
||||||
|
|
||||||
const items = await app.models.StarredModule.findOne(filter, options);
|
const items = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'claim';
|
filter.where.moduleFk = 'claim';
|
||||||
const claims = await app.models.StarredModule.findOne(filter, options);
|
const claims = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
let clients = await app.models.StarredModule.findOne(filter, options);
|
let clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'order';
|
filter.where.moduleFk = 'order';
|
||||||
let orders = await app.models.StarredModule.findOne(filter, options);
|
let orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'zone';
|
filter.where.moduleFk = 'zone';
|
||||||
const zones = await app.models.StarredModule.findOne(filter, options);
|
const zones = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(items.position).toEqual(1);
|
expect(items.position).toEqual(1);
|
||||||
expect(claims.position).toEqual(2);
|
expect(claims.position).toEqual(2);
|
||||||
|
@ -145,13 +145,13 @@ describe('setPosition()', () => {
|
||||||
expect(orders.position).toEqual(4);
|
expect(orders.position).toEqual(4);
|
||||||
expect(zones.position).toEqual(5);
|
expect(zones.position).toEqual(5);
|
||||||
|
|
||||||
await app.models.StarredModule.setPosition(ctx, 'customer', 'right', options);
|
await models.StarredModule.setPosition(ctx, 'customer', 'right', options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'order';
|
filter.where.moduleFk = 'order';
|
||||||
orders = await app.models.StarredModule.findOne(filter, options);
|
orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
clients = await app.models.StarredModule.findOne(filter, options);
|
clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(orders.position).toEqual(3);
|
expect(orders.position).toEqual(3);
|
||||||
expect(clients.position).toEqual(4);
|
expect(clients.position).toEqual(4);
|
||||||
|
@ -164,7 +164,7 @@ describe('setPosition()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should switch two modules after adding and deleting a module between them', async() => {
|
it('should switch two modules after adding and deleting a module between them', async() => {
|
||||||
const tx = await app.models.StarredModule.beginTransaction({});
|
const tx = await models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {
|
where: {
|
||||||
|
@ -176,25 +176,25 @@ describe('setPosition()', () => {
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'item', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'item', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'customer', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'order', options);
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'zone', options);
|
||||||
|
|
||||||
const items = await app.models.StarredModule.findOne(filter, options);
|
const items = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
let clients = await app.models.StarredModule.findOne(filter, options);
|
let clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'claim';
|
filter.where.moduleFk = 'claim';
|
||||||
const claims = await app.models.StarredModule.findOne(filter, options);
|
const claims = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'order';
|
filter.where.moduleFk = 'order';
|
||||||
let orders = await app.models.StarredModule.findOne(filter, options);
|
let orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'zone';
|
filter.where.moduleFk = 'zone';
|
||||||
const zones = await app.models.StarredModule.findOne(filter, options);
|
const zones = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(items.position).toEqual(1);
|
expect(items.position).toEqual(1);
|
||||||
expect(clients.position).toEqual(2);
|
expect(clients.position).toEqual(2);
|
||||||
|
@ -202,14 +202,14 @@ describe('setPosition()', () => {
|
||||||
expect(orders.position).toEqual(4);
|
expect(orders.position).toEqual(4);
|
||||||
expect(zones.position).toEqual(5);
|
expect(zones.position).toEqual(5);
|
||||||
|
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
|
await models.StarredModule.toggleStarredModule(ctx, 'claim', options);
|
||||||
await app.models.StarredModule.setPosition(ctx, 'customer', 'right', options);
|
await models.StarredModule.setPosition(ctx, 'customer', 'right', options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'customer';
|
filter.where.moduleFk = 'customer';
|
||||||
clients = await app.models.StarredModule.findOne(filter, options);
|
clients = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
filter.where.moduleFk = 'order';
|
filter.where.moduleFk = 'order';
|
||||||
orders = await app.models.StarredModule.findOne(filter, options);
|
orders = await models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
expect(orders.position).toEqual(2);
|
expect(orders.position).toEqual(2);
|
||||||
expect(clients.position).toEqual(4);
|
expect(clients.position).toEqual(4);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('toggleStarredModule()', () => {
|
describe('toggleStarredModule()', () => {
|
||||||
|
@ -21,16 +21,16 @@ describe('toggleStarredModule()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new starred module and then remove it by calling the method again with same args', async() => {
|
it('should create a new starred module and then remove it by calling the method again with same args', async() => {
|
||||||
const starredModule = await app.models.StarredModule.toggleStarredModule(ctx, 'order');
|
const starredModule = await models.StarredModule.toggleStarredModule(ctx, 'order');
|
||||||
let starredModules = await app.models.StarredModule.getStarredModules(ctx);
|
let starredModules = await models.StarredModule.getStarredModules(ctx);
|
||||||
|
|
||||||
expect(starredModules.length).toEqual(1);
|
expect(starredModules.length).toEqual(1);
|
||||||
expect(starredModule.moduleFk).toEqual('order');
|
expect(starredModule.moduleFk).toEqual('order');
|
||||||
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
|
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
|
||||||
expect(starredModule.position).toEqual(starredModules.length);
|
expect(starredModule.position).toEqual(starredModules.length);
|
||||||
|
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'order');
|
await models.StarredModule.toggleStarredModule(ctx, 'order');
|
||||||
starredModules = await app.models.StarredModule.getStarredModules(ctx);
|
starredModules = await models.StarredModule.getStarredModules(ctx);
|
||||||
|
|
||||||
expect(starredModules.length).toEqual(0);
|
expect(starredModules.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,7 +22,7 @@ module.exports = Self => {
|
||||||
let userId = ctx.req.accessToken.userId;
|
let userId = ctx.req.accessToken.userId;
|
||||||
let models = Self.app.models;
|
let models = Self.app.models;
|
||||||
|
|
||||||
let user = await models.Account.findById(userId, {
|
let user = await Self.findById(userId, {
|
||||||
fields: ['id', 'name', 'nickname', 'email', 'lang'],
|
fields: ['id', 'name', 'nickname', 'email', 'lang'],
|
||||||
include: {
|
include: {
|
||||||
relation: 'userConfig',
|
relation: 'userConfig',
|
|
@ -1,9 +1,14 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('privileges', {
|
Self.remoteMethod('privileges', {
|
||||||
description: 'Change role and hasGrant if user has privileges',
|
description: 'Change role and hasGrant if user has privileges',
|
||||||
accepts: [
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'ctx',
|
||||||
|
type: 'Object',
|
||||||
|
http: {source: 'context'}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
|
@ -39,9 +44,9 @@ module.exports = Self => {
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
const user = await models.Account.findById(userId, {fields: ['hasGrant']}, myOptions);
|
const user = await Self.findById(userId, {fields: ['hasGrant']}, myOptions);
|
||||||
|
|
||||||
const userToUpdate = await models.Account.findById(id, {
|
const userToUpdate = await Self.findById(id, {
|
||||||
fields: ['id', 'name', 'hasGrant', 'roleFk', 'password'],
|
fields: ['id', 'name', 'hasGrant', 'roleFk', 'password'],
|
||||||
include: {
|
include: {
|
||||||
relation: 'role',
|
relation: 'role',
|
||||||
|
@ -54,7 +59,7 @@ module.exports = Self => {
|
||||||
if (!user.hasGrant)
|
if (!user.hasGrant)
|
||||||
throw new UserError(`You don't have grant privilege`);
|
throw new UserError(`You don't have grant privilege`);
|
||||||
|
|
||||||
const hasRoleFromUser = await models.Account.hasRole(userId, userToUpdate.role().name, myOptions);
|
const hasRoleFromUser = await Self.hasRole(userId, userToUpdate.role().name, myOptions);
|
||||||
|
|
||||||
if (!hasRoleFromUser)
|
if (!hasRoleFromUser)
|
||||||
throw new UserError(`You don't own the role and you can't assign it to another user`);
|
throw new UserError(`You don't own the role and you can't assign it to another user`);
|
||||||
|
@ -64,7 +69,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
if (roleFk) {
|
if (roleFk) {
|
||||||
const role = await models.Role.findById(roleFk, {fields: ['name']}, myOptions);
|
const role = await models.Role.findById(roleFk, {fields: ['name']}, myOptions);
|
||||||
const hasRole = await models.Account.hasRole(userId, role.name, myOptions);
|
const hasRole = await Self.hasRole(userId, role.name, myOptions);
|
||||||
|
|
||||||
if (!hasRole)
|
if (!hasRole)
|
||||||
throw new UserError(`You don't own the role and you can't assign it to another user`);
|
throw new UserError(`You don't own the role and you can't assign it to another user`);
|
||||||
|
@ -73,6 +78,6 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
await userToUpdate.save(userToUpdate);
|
await userToUpdate.save(userToUpdate);
|
||||||
await models.UserAccount.sync(userToUpdate.name);
|
await models.Account.sync(userToUpdate.name);
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -20,7 +20,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
const usesEmail = user.indexOf('@') !== -1;
|
const usesEmail = user.indexOf('@') !== -1;
|
||||||
if (!usesEmail) {
|
if (!usesEmail) {
|
||||||
const account = await models.Account.findOne({
|
const account = await models.VnUser.findOne({
|
||||||
fields: ['email'],
|
fields: ['email'],
|
||||||
where: {name: user}
|
where: {name: user}
|
||||||
});
|
});
|
||||||
|
@ -28,7 +28,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await models.user.resetPassword({email: user, emailTemplate: 'recover-password'});
|
await Self.resetPassword({email: user, emailTemplate: 'recover-password'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code === 'EMAIL_NOT_FOUND')
|
if (err.code === 'EMAIL_NOT_FOUND')
|
||||||
return;
|
return;
|
|
@ -1,14 +1,14 @@
|
||||||
const md5 = require('md5');
|
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('login', {
|
Self.remoteMethod('signIn', {
|
||||||
description: 'Login a user with username/email and password',
|
description: 'Login a user with username/email and password',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'user',
|
arg: 'user',
|
||||||
type: 'String',
|
type: 'String',
|
||||||
description: 'The user name or email',
|
description: 'The user name or email',
|
||||||
|
http: {source: 'form'},
|
||||||
required: true
|
required: true
|
||||||
}, {
|
}, {
|
||||||
arg: 'password',
|
arg: 'password',
|
||||||
|
@ -21,20 +21,20 @@ module.exports = Self => {
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
path: `/login`,
|
path: `/signIn`,
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.login = async function(user, password) {
|
Self.signIn = async function(user, password) {
|
||||||
let $ = Self.app.models;
|
let models = Self.app.models;
|
||||||
let token;
|
let token;
|
||||||
let usesEmail = user.indexOf('@') !== -1;
|
let usesEmail = user.indexOf('@') !== -1;
|
||||||
|
|
||||||
let userInfo = usesEmail
|
let userInfo = usesEmail
|
||||||
? {email: user}
|
? {email: user}
|
||||||
: {username: user};
|
: {username: user};
|
||||||
let instance = await $.User.findOne({
|
let instance = await Self.findOne({
|
||||||
fields: ['username', 'password'],
|
fields: ['username', 'password'],
|
||||||
where: userInfo
|
where: userInfo
|
||||||
});
|
});
|
||||||
|
@ -42,29 +42,27 @@ module.exports = Self => {
|
||||||
let where = usesEmail
|
let where = usesEmail
|
||||||
? {email: user}
|
? {email: user}
|
||||||
: {name: user};
|
: {name: user};
|
||||||
let account = await Self.findOne({
|
let vnUser = await Self.findOne({
|
||||||
fields: ['active', 'password'],
|
fields: ['active'],
|
||||||
where
|
where
|
||||||
});
|
});
|
||||||
|
|
||||||
let validCredentials = instance && (
|
let validCredentials = instance
|
||||||
await instance.hasPassword(password) ||
|
&& await instance.hasPassword(password);
|
||||||
account.password == md5(password || '')
|
|
||||||
);
|
|
||||||
|
|
||||||
if (validCredentials) {
|
if (validCredentials) {
|
||||||
if (!account.active)
|
if (!vnUser.active)
|
||||||
throw new UserError('User disabled');
|
throw new UserError('User disabled');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await $.UserAccount.sync(instance.username, password);
|
await models.Account.sync(instance.username, password);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(err);
|
console.warn(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let loginInfo = Object.assign({password}, userInfo);
|
let loginInfo = Object.assign({password}, userInfo);
|
||||||
token = await $.User.login(loginInfo, 'user');
|
token = await Self.login(loginInfo, 'user');
|
||||||
return {token: token.id};
|
return {token: token.id};
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('account privileges()', () => {
|
describe('VnUser privileges()', () => {
|
||||||
const employeeId = 1;
|
const employeeId = 1;
|
||||||
const developerId = 9;
|
const developerId = 9;
|
||||||
const sysadminId = 66;
|
const sysadminId = 66;
|
||||||
|
@ -10,13 +10,13 @@ describe('account privileges()', () => {
|
||||||
|
|
||||||
it('should throw an error when user not has privileges', async() => {
|
it('should throw an error when user not has privileges', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: developerId}}};
|
const ctx = {req: {accessToken: {userId: developerId}}};
|
||||||
const tx = await models.Account.beginTransaction({});
|
const tx = await models.VnUser.beginTransaction({});
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
await models.Account.privileges(ctx, employeeId, null, true, options);
|
await models.VnUser.privileges(ctx, employeeId, null, true, options);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -29,13 +29,13 @@ describe('account privileges()', () => {
|
||||||
|
|
||||||
it('should throw an error when user has privileges but not has the role', async() => {
|
it('should throw an error when user has privileges but not has the role', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
||||||
const tx = await models.Account.beginTransaction({});
|
const tx = await models.VnUser.beginTransaction({});
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
await models.Account.privileges(ctx, employeeId, rootId, null, options);
|
await models.VnUser.privileges(ctx, employeeId, rootId, null, options);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -48,13 +48,13 @@ describe('account privileges()', () => {
|
||||||
|
|
||||||
it('should throw an error when user has privileges but not has the role from user', async() => {
|
it('should throw an error when user has privileges but not has the role from user', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
||||||
const tx = await models.Account.beginTransaction({});
|
const tx = await models.VnUser.beginTransaction({});
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
await models.Account.privileges(ctx, itBossId, developerId, null, options);
|
await models.VnUser.privileges(ctx, itBossId, developerId, null, options);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -67,7 +67,7 @@ describe('account privileges()', () => {
|
||||||
|
|
||||||
it('should change role', async() => {
|
it('should change role', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
||||||
const tx = await models.Account.beginTransaction({});
|
const tx = await models.VnUser.beginTransaction({});
|
||||||
|
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
const agency = await models.Role.findOne({
|
const agency = await models.Role.findOne({
|
||||||
|
@ -79,8 +79,8 @@ describe('account privileges()', () => {
|
||||||
let error;
|
let error;
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
await models.Account.privileges(ctx, clarkKent, agency.id, null, options);
|
await models.VnUser.privileges(ctx, clarkKent, agency.id, null, options);
|
||||||
result = await models.Account.findById(clarkKent, null, options);
|
result = await models.VnUser.findById(clarkKent, null, options);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -94,14 +94,14 @@ describe('account privileges()', () => {
|
||||||
|
|
||||||
it('should change hasGrant', async() => {
|
it('should change hasGrant', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
const ctx = {req: {accessToken: {userId: sysadminId}}};
|
||||||
const tx = await models.Account.beginTransaction({});
|
const tx = await models.VnUser.beginTransaction({});
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
await models.Account.privileges(ctx, clarkKent, null, true, options);
|
await models.VnUser.privileges(ctx, clarkKent, null, true, options);
|
||||||
result = await models.Account.findById(clarkKent, null, options);
|
result = await models.VnUser.findById(clarkKent, null, options);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
|
@ -1,25 +1,25 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('account login()', () => {
|
describe('VnUser signIn()', () => {
|
||||||
describe('when credentials are correct', () => {
|
describe('when credentials are correct', () => {
|
||||||
it('should return the token', async() => {
|
it('should return the token', async() => {
|
||||||
let login = await app.models.Account.login('salesAssistant', 'nightmare');
|
let login = await models.VnUser.signIn('salesAssistant', 'nightmare');
|
||||||
let accessToken = await app.models.AccessToken.findById(login.token);
|
let accessToken = await models.AccessToken.findById(login.token);
|
||||||
let ctx = {req: {accessToken: accessToken}};
|
let ctx = {req: {accessToken: accessToken}};
|
||||||
|
|
||||||
expect(login.token).toBeDefined();
|
expect(login.token).toBeDefined();
|
||||||
|
|
||||||
await app.models.Account.logout(ctx);
|
await models.VnUser.signOut(ctx);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the token if the user doesnt exist but the client does', async() => {
|
it('should return the token if the user doesnt exist but the client does', async() => {
|
||||||
let login = await app.models.Account.login('PetterParker', 'nightmare');
|
let login = await models.VnUser.signIn('PetterParker', 'nightmare');
|
||||||
let accessToken = await app.models.AccessToken.findById(login.token);
|
let accessToken = await models.AccessToken.findById(login.token);
|
||||||
let ctx = {req: {accessToken: accessToken}};
|
let ctx = {req: {accessToken: accessToken}};
|
||||||
|
|
||||||
expect(login.token).toBeDefined();
|
expect(login.token).toBeDefined();
|
||||||
|
|
||||||
await app.models.Account.logout(ctx);
|
await models.VnUser.signOut(ctx);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ describe('account login()', () => {
|
||||||
let error;
|
let error;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.Account.login('IDontExist', 'TotallyWrongPassword');
|
await models.VnUser.signIn('IDontExist', 'TotallyWrongPassword');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('account logout()', () => {
|
describe('VnUser signOut()', () => {
|
||||||
it('should logout and remove token after valid login', async() => {
|
it('should logout and remove token after valid login', async() => {
|
||||||
let loginResponse = await app.models.Account.login('buyer', 'nightmare');
|
let loginResponse = await models.VnUser.signOut('buyer', 'nightmare');
|
||||||
let accessToken = await app.models.AccessToken.findById(loginResponse.token);
|
let accessToken = await models.AccessToken.findById(loginResponse.token);
|
||||||
let ctx = {req: {accessToken: accessToken}};
|
let ctx = {req: {accessToken: accessToken}};
|
||||||
|
|
||||||
let logoutResponse = await app.models.Account.logout(ctx);
|
let logoutResponse = await models.VnUser.signOut(ctx);
|
||||||
let tokenAfterLogout = await app.models.AccessToken.findById(loginResponse.token);
|
let tokenAfterLogout = await models.AccessToken.findById(loginResponse.token);
|
||||||
|
|
||||||
expect(logoutResponse).toBeTrue();
|
expect(logoutResponse).toBeTrue();
|
||||||
expect(tokenAfterLogout).toBeNull();
|
expect(tokenAfterLogout).toBeNull();
|
||||||
|
@ -18,7 +18,7 @@ describe('account logout()', () => {
|
||||||
let ctx = {req: {accessToken: {id: 'invalidToken'}}};
|
let ctx = {req: {accessToken: {id: 'invalidToken'}}};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await app.models.Account.logout(ctx);
|
response = await models.VnUser.signOut(ctx);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ describe('account logout()', () => {
|
||||||
let ctx = {req: {accessToken: null}};
|
let ctx = {req: {accessToken: null}};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await app.models.Account.logout(ctx);
|
response = await models.VnUser.signOut(ctx);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
|
@ -1,7 +1,4 @@
|
||||||
{
|
{
|
||||||
"Account": {
|
|
||||||
"dataSource": "vn"
|
|
||||||
},
|
|
||||||
"AccountingType": {
|
"AccountingType": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
@ -125,10 +122,10 @@
|
||||||
"UserConfigView": {
|
"UserConfigView": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"UserLog": {
|
"Warehouse": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"Warehouse": {
|
"VnUser": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"OsTicket": {
|
"OsTicket": {
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
/* eslint max-len: ["error", { "code": 150 }]*/
|
|
||||||
const md5 = require('md5');
|
|
||||||
const LoopBackContext = require('loopback-context');
|
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
|
||||||
require('../methods/account/login')(Self);
|
|
||||||
require('../methods/account/logout')(Self);
|
|
||||||
require('../methods/account/acl')(Self);
|
|
||||||
require('../methods/account/change-password')(Self);
|
|
||||||
require('../methods/account/set-password')(Self);
|
|
||||||
require('../methods/account/recover-password')(Self);
|
|
||||||
require('../methods/account/validate-token')(Self);
|
|
||||||
require('../methods/account/privileges')(Self);
|
|
||||||
|
|
||||||
// Validations
|
|
||||||
|
|
||||||
Self.validatesFormatOf('email', {
|
|
||||||
message: 'Invalid email',
|
|
||||||
allowNull: true,
|
|
||||||
allowBlank: true,
|
|
||||||
with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.validatesUniquenessOf('name', {
|
|
||||||
message: `A client with that Web User name already exists`
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx) {
|
|
||||||
if (ctx.currentInstance && ctx.currentInstance.id && ctx.data && ctx.data.password)
|
|
||||||
ctx.data.password = md5(ctx.data.password);
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.afterRemote('prototype.patchAttributes', async(ctx, instance) => {
|
|
||||||
if (!ctx.args || !ctx.args.data.email) return;
|
|
||||||
const models = Self.app.models;
|
|
||||||
|
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
|
||||||
const httpCtx = {req: loopBackContext.active};
|
|
||||||
const httpRequest = httpCtx.req.http.req;
|
|
||||||
const headers = httpRequest.headers;
|
|
||||||
const origin = headers.origin;
|
|
||||||
const url = origin.split(':');
|
|
||||||
|
|
||||||
const userId = ctx.instance.id;
|
|
||||||
const user = await models.user.findById(userId);
|
|
||||||
|
|
||||||
class Mailer {
|
|
||||||
async send(verifyOptions, cb) {
|
|
||||||
const params = {
|
|
||||||
url: verifyOptions.verifyHref,
|
|
||||||
recipient: verifyOptions.to,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
const email = new Email('email-verify', params);
|
|
||||||
email.send();
|
|
||||||
|
|
||||||
cb(null, verifyOptions.to);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
type: 'email',
|
|
||||||
to: instance.email,
|
|
||||||
from: {},
|
|
||||||
redirect: `${origin}/#!/account/${instance.id}/basic-data?emailConfirmed`,
|
|
||||||
template: false,
|
|
||||||
mailer: new Mailer,
|
|
||||||
host: url[1].split('/')[2],
|
|
||||||
port: url[2],
|
|
||||||
protocol: url[0],
|
|
||||||
user: Self
|
|
||||||
};
|
|
||||||
|
|
||||||
await user.verify(options);
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.remoteMethod('getCurrentUserData', {
|
|
||||||
description: 'Gets the current user data',
|
|
||||||
accepts: [
|
|
||||||
{
|
|
||||||
arg: 'ctx',
|
|
||||||
type: 'object',
|
|
||||||
http: {source: 'context'}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
returns: {
|
|
||||||
type: 'object',
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
verb: 'GET',
|
|
||||||
path: '/getCurrentUserData'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.getCurrentUserData = async function(ctx) {
|
|
||||||
let userId = ctx.req.accessToken.userId;
|
|
||||||
return await Self.findById(userId, {
|
|
||||||
fields: ['id', 'name', 'nickname']
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if user has a role.
|
|
||||||
*
|
|
||||||
* @param {Integer} userId The user id
|
|
||||||
* @param {String} name The role name
|
|
||||||
* @param {object} options Options
|
|
||||||
* @return {Boolean} %true if user has the role, %false otherwise
|
|
||||||
*/
|
|
||||||
Self.hasRole = async function(userId, name, options) {
|
|
||||||
let roles = await Self.getRoles(userId, options);
|
|
||||||
return roles.some(role => role == name);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all user roles.
|
|
||||||
*
|
|
||||||
* @param {Integer} userId The user id
|
|
||||||
* @param {object} options Options
|
|
||||||
* @return {object} User role list
|
|
||||||
*/
|
|
||||||
Self.getRoles = async(userId, options) => {
|
|
||||||
let result = await Self.rawSql(
|
|
||||||
`SELECT r.name
|
|
||||||
FROM account.user u
|
|
||||||
JOIN account.roleRole rr ON rr.role = u.role
|
|
||||||
JOIN account.role r ON r.id = rr.inheritsFrom
|
|
||||||
WHERE u.id = ?`, [userId], options);
|
|
||||||
|
|
||||||
let roles = [];
|
|
||||||
for (const role of result)
|
|
||||||
roles.push(role.name);
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -54,8 +54,8 @@ module.exports = Self => {
|
||||||
const writeRole = dmsType.writeRole() && dmsType.writeRole().name;
|
const writeRole = dmsType.writeRole() && dmsType.writeRole().name;
|
||||||
const requiredRole = readRole || writeRole;
|
const requiredRole = readRole || writeRole;
|
||||||
|
|
||||||
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole, options);
|
const hasRequiredRole = await models.VnUser.hasRole(myUserId, requiredRole, options);
|
||||||
const isRoot = await models.Account.hasRole(myUserId, 'root', options);
|
const isRoot = await models.VnUser.hasRole(myUserId, 'root', options);
|
||||||
|
|
||||||
if (isRoot || hasRequiredRole)
|
if (isRoot || hasRequiredRole)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"relations": {
|
"relations": {
|
||||||
"user": {
|
"user": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Account",
|
"model": "VnUser",
|
||||||
"foreignKey": "userFk"
|
"foreignKey": "userFk"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -53,8 +53,8 @@ module.exports = Self => {
|
||||||
const writeRole = collection.writeRole() && collection.writeRole().name;
|
const writeRole = collection.writeRole() && collection.writeRole().name;
|
||||||
const requiredRole = readRole || writeRole;
|
const requiredRole = readRole || writeRole;
|
||||||
|
|
||||||
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole, options);
|
const hasRequiredRole = await models.VnUser.hasRole(myUserId, requiredRole, options);
|
||||||
const isRoot = await models.Account.hasRole(myUserId, 'root', options);
|
const isRoot = await models.VnUser.hasRole(myUserId, 'root', options);
|
||||||
|
|
||||||
if (isRoot || hasRequiredRole)
|
if (isRoot || hasRequiredRole)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,161 +1,112 @@
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const sharp = require('sharp');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const readChunk = require('read-chunk');
|
const gm = require('gm');
|
||||||
const imageType = require('image-type');
|
|
||||||
const bmp = require('bmp-js');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/image/download')(Self);
|
require('../methods/image/download')(Self);
|
||||||
require('../methods/image/upload')(Self);
|
require('../methods/image/upload')(Self);
|
||||||
|
require('../methods/image/scrub')(Self);
|
||||||
|
|
||||||
// Function extracted from jimp package (utils)
|
Self.resize = async function({collectionName, srcFile, fileName, entityId}) {
|
||||||
function scan(image, x, y, w, h, f) {
|
|
||||||
// round input
|
|
||||||
x = Math.round(x);
|
|
||||||
y = Math.round(y);
|
|
||||||
w = Math.round(w);
|
|
||||||
h = Math.round(h);
|
|
||||||
|
|
||||||
for (let _y = y; _y < y + h; _y++) {
|
|
||||||
for (let _x = x; _x < x + w; _x++) {
|
|
||||||
const idx = (image.bitmap.width * _y + _x) << 2;
|
|
||||||
f.call(image, _x, _y, idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function extracted from jimp package (type-bmp)
|
|
||||||
function fromAGBR(bitmap) {
|
|
||||||
return scan({bitmap}, 0, 0, bitmap.width, bitmap.height, function(
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
index
|
|
||||||
) {
|
|
||||||
const alpha = this.bitmap.data[index + 0];
|
|
||||||
const blue = this.bitmap.data[index + 1];
|
|
||||||
const green = this.bitmap.data[index + 2];
|
|
||||||
const red = this.bitmap.data[index + 3];
|
|
||||||
|
|
||||||
this.bitmap.data[index + 0] = red;
|
|
||||||
this.bitmap.data[index + 1] = green;
|
|
||||||
this.bitmap.data[index + 2] = blue;
|
|
||||||
this.bitmap.data[index + 3] = bitmap.is_with_alpha ? alpha : 0xff;
|
|
||||||
}).bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
Self.registerImage = async(collectionName, srcFilePath, fileName, entityId) => {
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const tx = await Self.beginTransaction({});
|
|
||||||
const myOptions = {transaction: tx};
|
|
||||||
|
|
||||||
try {
|
const collection = await models.ImageCollection.findOne(
|
||||||
const collection = await models.ImageCollection.findOne({
|
{
|
||||||
fields: [
|
fields: [
|
||||||
'id',
|
'id',
|
||||||
'name',
|
|
||||||
'maxWidth',
|
'maxWidth',
|
||||||
'maxHeight',
|
'maxHeight',
|
||||||
'model',
|
'model',
|
||||||
'property'
|
'property',
|
||||||
],
|
],
|
||||||
where: {name: collectionName},
|
where: {name: collectionName},
|
||||||
include: {
|
include: {
|
||||||
relation: 'sizes',
|
relation: 'sizes',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ['width', 'height', 'crop']
|
fields: ['width', 'height', 'crop'],
|
||||||
}
|
|
||||||
}
|
|
||||||
}, myOptions);
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
name: fileName,
|
|
||||||
collectionFk: collectionName
|
|
||||||
};
|
|
||||||
const newImage = await Self.upsertWithWhere(data, {
|
|
||||||
name: fileName,
|
|
||||||
collectionFk: collectionName,
|
|
||||||
updated: Date.vnNow()
|
|
||||||
}, myOptions);
|
|
||||||
|
|
||||||
// Resizes and saves the image
|
|
||||||
const container = await models.ImageContainer.container(collectionName);
|
|
||||||
const rootPath = container.client.root;
|
|
||||||
const collectionDir = path.join(rootPath, collectionName);
|
|
||||||
const dstDir = path.join(collectionDir, 'full');
|
|
||||||
const dstFile = path.join(dstDir, fileName);
|
|
||||||
|
|
||||||
const buffer = readChunk.sync(srcFilePath, 0, 12);
|
|
||||||
const type = imageType(buffer);
|
|
||||||
|
|
||||||
let sharpOptions;
|
|
||||||
let imgSrc = srcFilePath;
|
|
||||||
if (type.mime == 'image/bmp') {
|
|
||||||
const bmpBuffer = fs.readFileSync(srcFilePath);
|
|
||||||
const bmpData = fromAGBR(bmp.decode(bmpBuffer));
|
|
||||||
imgSrc = bmpData.data;
|
|
||||||
sharpOptions = {
|
|
||||||
raw: {
|
|
||||||
width: bmpData.width,
|
|
||||||
height: bmpData.height,
|
|
||||||
channels: 4
|
|
||||||
},
|
},
|
||||||
failOn: 'none'
|
},
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const resizeOpts = {
|
// Insert image row
|
||||||
withoutEnlargement: true,
|
const imageName = path.parse(fileName).name;
|
||||||
fit: 'inside'
|
await models.Image.upsertWithWhere(
|
||||||
};
|
{
|
||||||
|
name: imageName,
|
||||||
await fs.mkdir(dstDir, {recursive: true});
|
collectionFk: collectionName
|
||||||
await sharp(imgSrc, sharpOptions)
|
},
|
||||||
.resize(collection.maxWidth, collection.maxHeight, resizeOpts)
|
{
|
||||||
.png()
|
name: imageName,
|
||||||
.toFile(dstFile);
|
collectionFk: collectionName,
|
||||||
|
updated: Date.vnNow() / 1000,
|
||||||
const sizes = collection.sizes();
|
|
||||||
for (let size of sizes) {
|
|
||||||
const dstDir = path.join(collectionDir, `${size.width}x${size.height}`);
|
|
||||||
const dstFile = path.join(dstDir, fileName);
|
|
||||||
const resizeOpts = {
|
|
||||||
withoutEnlargement: true,
|
|
||||||
fit: size.crop ? 'cover' : 'inside'
|
|
||||||
};
|
|
||||||
|
|
||||||
await fs.mkdir(dstDir, {recursive: true});
|
|
||||||
await sharp(imgSrc, sharpOptions)
|
|
||||||
.resize(size.width, size.height, resizeOpts)
|
|
||||||
.png()
|
|
||||||
.toFile(dstFile);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const model = models[collection.model];
|
// Update entity image file name
|
||||||
|
const model = models[collection.model];
|
||||||
|
if (!model) throw new Error('No matching model found');
|
||||||
|
|
||||||
if (!model)
|
const entity = await model.findById(entityId);
|
||||||
throw new Error('Matching model not found');
|
if (entity) {
|
||||||
|
await entity.updateAttribute(
|
||||||
|
collection.property,
|
||||||
|
imageName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const item = await model.findById(entityId, null, myOptions);
|
// Resize
|
||||||
if (item) {
|
const container = await models.ImageContainer.container(
|
||||||
await item.updateAttribute(
|
collectionName
|
||||||
collection.property,
|
);
|
||||||
fileName,
|
const rootPath = container.client.root;
|
||||||
myOptions
|
const collectionDir = path.join(rootPath, collectionName);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fs.existsSync(srcFilePath))
|
// To max size
|
||||||
await fs.unlink(srcFilePath);
|
const {maxWidth, maxHeight} = collection;
|
||||||
|
const fullSizePath = path.join(collectionDir, 'full');
|
||||||
|
const toFullSizePath = `${fullSizePath}/${fileName}`;
|
||||||
|
|
||||||
await tx.commit();
|
await fs.mkdir(fullSizePath, {recursive: true});
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
gm(srcFile)
|
||||||
|
.resize(maxWidth, maxHeight, '>')
|
||||||
|
.setFormat('png')
|
||||||
|
.quality(100)
|
||||||
|
.write(toFullSizePath, function(err) {
|
||||||
|
if (err) reject(err);
|
||||||
|
if (!err) resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return newImage;
|
// To collection sizes
|
||||||
} catch (e) {
|
for (const size of collection.sizes()) {
|
||||||
await tx.rollback();
|
const {width, height} = size;
|
||||||
throw e;
|
|
||||||
|
const sizePath = path.join(collectionDir, `${width}x${height}`);
|
||||||
|
const toSizePath = `${sizePath}/${fileName}`;
|
||||||
|
|
||||||
|
await fs.mkdir(sizePath, {recursive: true});
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const gmInstance = gm(srcFile);
|
||||||
|
|
||||||
|
if (size.crop) {
|
||||||
|
gmInstance
|
||||||
|
.resize(width, height, '^')
|
||||||
|
.gravity('Center')
|
||||||
|
.crop(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size.crop) gmInstance.resize(width, height, '>');
|
||||||
|
|
||||||
|
gmInstance
|
||||||
|
.setFormat('png')
|
||||||
|
.quality(100)
|
||||||
|
.write(toSizePath, function(err) {
|
||||||
|
if (err) reject(err);
|
||||||
|
if (!err) resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Account",
|
"model": "VnUser",
|
||||||
"foreignKey": "authorFk"
|
"foreignKey": "authorFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Account",
|
"model": "VnUser",
|
||||||
"foreignKey": "userFk"
|
"foreignKey": "userFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('loopback model Company', () => {
|
describe('loopback model Company', () => {
|
||||||
it('should check that the company FTH doesnt exists', async() => {
|
it('should check that the company FTH doesnt exists', async() => {
|
||||||
let result = await app.models.Company.findOne({where: {code: 'FTH'}});
|
let result = await models.Company.findOne({where: {code: 'FTH'}});
|
||||||
|
|
||||||
expect(result).toBeFalsy();
|
expect(result).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
describe('Dms', () => {
|
describe('Dms', () => {
|
||||||
const Dms = app.models.Dms;
|
const Dms = models.Dms;
|
||||||
|
|
||||||
describe('getFile()', () => {
|
describe('getFile()', () => {
|
||||||
it('should return a response with text content-type', async() => {
|
it('should return a response with text content-type', async() => {
|
||||||
|
@ -23,7 +23,7 @@ describe('Dms', () => {
|
||||||
it('should return an error for a record does not exists', async() => {
|
it('should return an error for a record does not exists', async() => {
|
||||||
let error = {};
|
let error = {};
|
||||||
try {
|
try {
|
||||||
await app.models.Dms.getFile('NotExistentId');
|
await models.Dms.getFile('NotExistentId');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('account recoverPassword()', () => {
|
describe('VnUser recoverPassword()', () => {
|
||||||
const userId = 1107;
|
const userId = 1107;
|
||||||
|
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
|
@ -21,9 +21,9 @@ describe('account recoverPassword()', () => {
|
||||||
|
|
||||||
it('should send email with token', async() => {
|
it('should send email with token', async() => {
|
||||||
const userId = 1107;
|
const userId = 1107;
|
||||||
const user = await models.Account.findById(userId);
|
const user = await models.VnUser.findById(userId);
|
||||||
|
|
||||||
await models.Account.recoverPassword(user.email);
|
await models.VnUser.recoverPassword(user.email);
|
||||||
|
|
||||||
const result = await models.AccessToken.findOne({where: {userId: userId}});
|
const result = await models.AccessToken.findOne({where: {userId: userId}});
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('loopback model Account', () => {
|
describe('loopback model VnUser', () => {
|
||||||
it('should return true if the user has the given role', async() => {
|
it('should return true if the user has the given role', async() => {
|
||||||
let result = await models.Account.hasRole(1, 'employee');
|
let result = await models.VnUser.hasRole(1, 'employee');
|
||||||
|
|
||||||
expect(result).toBeTruthy();
|
expect(result).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if the user doesnt have the given role', async() => {
|
it('should return false if the user doesnt have the given role', async() => {
|
||||||
let result = await models.Account.hasRole(1, 'administrator');
|
let result = await models.VnUser.hasRole(1, 'administrator');
|
||||||
|
|
||||||
expect(result).toBeFalsy();
|
expect(result).toBeFalsy();
|
||||||
});
|
});
|
|
@ -26,7 +26,7 @@
|
||||||
"relations": {
|
"relations": {
|
||||||
"user": {
|
"user": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Account",
|
"model": "VnUser",
|
||||||
"foreignKey": "userFk"
|
"foreignKey": "userFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@
|
||||||
"model": "Company",
|
"model": "Company",
|
||||||
"foreignKey": "companyFk"
|
"foreignKey": "companyFk"
|
||||||
},
|
},
|
||||||
"account": {
|
"VnUser": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Account",
|
"model": "VnUser",
|
||||||
"foreignKey": "userFk"
|
"foreignKey": "userFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
const LoopBackContext = require('loopback-context');
|
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = function(Self) {
|
|
||||||
Self.on('resetPasswordRequest', async function(info) {
|
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
|
||||||
const httpCtx = {req: loopBackContext.active};
|
|
||||||
const httpRequest = httpCtx.req.http.req;
|
|
||||||
const headers = httpRequest.headers;
|
|
||||||
const origin = headers.origin;
|
|
||||||
|
|
||||||
const user = await Self.app.models.Account.findById(info.user.id);
|
|
||||||
const params = {
|
|
||||||
recipient: info.email,
|
|
||||||
lang: user.lang,
|
|
||||||
url: `${origin}/#!/reset-password?access_token=${info.accessToken.id}`
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = Object.assign({}, info.options);
|
|
||||||
for (const param in options)
|
|
||||||
params[param] = options[param];
|
|
||||||
|
|
||||||
const email = new Email(options.emailTemplate, params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"name": "user",
|
|
||||||
"base": "User",
|
|
||||||
"options": {
|
|
||||||
"mysql": {
|
|
||||||
"table": "salix.User"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"id": true,
|
|
||||||
"type": "number",
|
|
||||||
"forceId": false
|
|
||||||
},
|
|
||||||
"username":{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
const vnModel = require('vn-loopback/common/models/vn-model');
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
const {Email} = require('vn-print');
|
||||||
|
|
||||||
|
module.exports = function(Self) {
|
||||||
|
vnModel(Self);
|
||||||
|
|
||||||
|
require('../methods/vn-user/signIn')(Self);
|
||||||
|
require('../methods/vn-user/acl')(Self);
|
||||||
|
require('../methods/vn-user/recover-password')(Self);
|
||||||
|
require('../methods/vn-user/validate-token')(Self);
|
||||||
|
require('../methods/vn-user/privileges')(Self);
|
||||||
|
|
||||||
|
// Validations
|
||||||
|
|
||||||
|
Self.validatesFormatOf('email', {
|
||||||
|
message: 'Invalid email',
|
||||||
|
allowNull: true,
|
||||||
|
allowBlank: true,
|
||||||
|
with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.validatesUniquenessOf('name', {
|
||||||
|
message: `A client with that Web User name already exists`
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.remoteMethod('getCurrentUserData', {
|
||||||
|
description: 'Gets the current user data',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'ctx',
|
||||||
|
type: 'Object',
|
||||||
|
http: {source: 'context'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
verb: 'GET',
|
||||||
|
path: '/getCurrentUserData'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getCurrentUserData = async function(ctx) {
|
||||||
|
let userId = ctx.req.accessToken.userId;
|
||||||
|
return await Self.findById(userId, {
|
||||||
|
fields: ['id', 'name', 'nickname']
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if user has a role.
|
||||||
|
*
|
||||||
|
* @param {Integer} userId The user id
|
||||||
|
* @param {String} name The role name
|
||||||
|
* @param {Object} options Options
|
||||||
|
* @return {Boolean} %true if user has the role, %false otherwise
|
||||||
|
*/
|
||||||
|
Self.hasRole = async function(userId, name, options) {
|
||||||
|
const roles = await Self.getRoles(userId, options);
|
||||||
|
return roles.some(role => role == name);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all user roles.
|
||||||
|
*
|
||||||
|
* @param {Integer} userId The user id
|
||||||
|
* @param {Object} options Options
|
||||||
|
* @return {Object} User role list
|
||||||
|
*/
|
||||||
|
Self.getRoles = async(userId, options) => {
|
||||||
|
const result = await Self.rawSql(
|
||||||
|
`SELECT r.name
|
||||||
|
FROM account.user u
|
||||||
|
JOIN account.roleRole rr ON rr.role = u.role
|
||||||
|
JOIN account.role r ON r.id = rr.inheritsFrom
|
||||||
|
WHERE u.id = ?`, [userId], options);
|
||||||
|
|
||||||
|
const roles = [];
|
||||||
|
for (const role of result)
|
||||||
|
roles.push(role.name);
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
};
|
||||||
|
|
||||||
|
Self.on('resetPasswordRequest', async function(info) {
|
||||||
|
const loopBackContext = LoopBackContext.getCurrentContext();
|
||||||
|
const httpCtx = {req: loopBackContext.active};
|
||||||
|
const httpRequest = httpCtx.req.http.req;
|
||||||
|
const headers = httpRequest.headers;
|
||||||
|
const origin = headers.origin;
|
||||||
|
|
||||||
|
const user = await Self.app.models.VnUser.findById(info.user.id);
|
||||||
|
const params = {
|
||||||
|
recipient: info.email,
|
||||||
|
lang: user.lang,
|
||||||
|
url: `${origin}/#!/reset-password?access_token=${info.accessToken.id}`
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = Object.assign({}, info.options);
|
||||||
|
for (const param in options)
|
||||||
|
params[param] = options[param];
|
||||||
|
|
||||||
|
const email = new Email(options.emailTemplate, params);
|
||||||
|
|
||||||
|
return email.send();
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,11 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "Account",
|
"name": "VnUser",
|
||||||
"base": "VnModel",
|
"base": "User",
|
||||||
|
"validateUpsert": true,
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "account.user"
|
"table": "account.user"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"resetPasswordTokenTTL": "604800",
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
|
@ -15,6 +17,19 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "bcryptPassword"
|
||||||
|
}
|
||||||
|
},
|
||||||
"roleFk": {
|
"roleFk": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
@ -27,10 +42,6 @@
|
||||||
"lang": {
|
"lang": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"password": {
|
|
||||||
"type": "string",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"bcryptPassword": {
|
"bcryptPassword": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -40,9 +51,6 @@
|
||||||
"email": {
|
"email": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"emailVerified": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"created": {
|
"created": {
|
||||||
"type": "date"
|
"type": "date"
|
||||||
},
|
},
|
||||||
|
@ -86,7 +94,7 @@
|
||||||
},
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
{
|
{
|
||||||
"property": "login",
|
"property": "signIn",
|
||||||
"accessType": "EXECUTE",
|
"accessType": "EXECUTE",
|
||||||
"principalType": "ROLE",
|
"principalType": "ROLE",
|
||||||
"principalId": "$everyone",
|
"principalId": "$everyone",
|
||||||
|
@ -100,13 +108,6 @@
|
||||||
"permission": "ALLOW"
|
"permission": "ALLOW"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"property": "logout",
|
|
||||||
"accessType": "EXECUTE",
|
|
||||||
"principalType": "ROLE",
|
|
||||||
"principalId": "$authenticated",
|
|
||||||
"permission": "ALLOW"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"property": "validateToken",
|
"property": "validateToken",
|
||||||
"accessType": "EXECUTE",
|
"accessType": "EXECUTE",
|
||||||
"principalType": "ROLE",
|
"principalType": "ROLE",
|
|
@ -53,7 +53,7 @@ async function test() {
|
||||||
const JunitReporter = require('jasmine-reporters');
|
const JunitReporter = require('jasmine-reporters');
|
||||||
jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
|
jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
|
||||||
|
|
||||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
|
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
|
||||||
jasmine.exitOnCompletion = true;
|
jasmine.exitOnCompletion = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`(
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Creación de facturas emitidas.
|
* Creación de facturas emitidas.
|
||||||
* requiere previamente tabla ticketToInvoice(id).
|
* requiere previamente tabla tmp.ticketToInvoice(id).
|
||||||
*
|
*
|
||||||
* @param vSerial serie a la cual se hace la factura
|
* @param vSerial serie a la cual se hace la factura
|
||||||
* @param vInvoiceDate fecha de la factura
|
* @param vInvoiceDate fecha de la factura
|
||||||
|
@ -36,13 +36,13 @@ BEGIN
|
||||||
|
|
||||||
SELECT t.clientFk, t.companyFk
|
SELECT t.clientFk, t.companyFk
|
||||||
INTO vClient, vCompany
|
INTO vClient, vCompany
|
||||||
FROM ticketToInvoice tt
|
FROM tmp.ticketToInvoice tt
|
||||||
JOIN ticket t ON t.id = tt.id
|
JOIN ticket t ON t.id = tt.id
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
-- Eliminem de ticketToInvoice els tickets que no han de ser facturats
|
-- Eliminem de tmp.ticketToInvoice els tickets que no han de ser facturats
|
||||||
DELETE ti.*
|
DELETE ti.*
|
||||||
FROM ticketToInvoice ti
|
FROM tmp.ticketToInvoice ti
|
||||||
JOIN ticket t ON t.id = ti.id
|
JOIN ticket t ON t.id = ti.id
|
||||||
JOIN sale s ON s.ticketFk = t.id
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
JOIN item i ON i.id = s.itemFk
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
@ -57,7 +57,7 @@ BEGIN
|
||||||
|
|
||||||
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100), ts.id
|
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100), ts.id
|
||||||
INTO vIsAnySaleToInvoice, vIsAnyServiceToInvoice
|
INTO vIsAnySaleToInvoice, vIsAnyServiceToInvoice
|
||||||
FROM ticketToInvoice t
|
FROM tmp.ticketToInvoice t
|
||||||
LEFT JOIN sale s ON s.ticketFk = t.id
|
LEFT JOIN sale s ON s.ticketFk = t.id
|
||||||
LEFT JOIN ticketService ts ON ts.ticketFk = t.id;
|
LEFT JOIN ticketService ts ON ts.ticketFk = t.id;
|
||||||
|
|
||||||
|
@ -100,13 +100,13 @@ BEGIN
|
||||||
WHERE id = vNewInvoiceId;
|
WHERE id = vNewInvoiceId;
|
||||||
|
|
||||||
UPDATE ticket t
|
UPDATE ticket t
|
||||||
JOIN ticketToInvoice ti ON ti.id = t.id
|
JOIN tmp.ticketToInvoice ti ON ti.id = t.id
|
||||||
SET t.refFk = vNewRef;
|
SET t.refFk = vNewRef;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
|
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
|
||||||
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
|
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
|
||||||
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
|
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
|
||||||
FROM ticketToInvoice ti
|
FROM tmp.ticketToInvoice ti
|
||||||
LEFT JOIN ticketState ts ON ti.id = ts.ticket
|
LEFT JOIN ticketState ts ON ti.id = ts.ticket
|
||||||
JOIN state s
|
JOIN state s
|
||||||
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
|
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
|
||||||
|
@ -116,7 +116,7 @@ BEGIN
|
||||||
|
|
||||||
INSERT INTO ticketLog (action, userFk, originFk, description)
|
INSERT INTO ticketLog (action, userFk, originFk, description)
|
||||||
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
||||||
FROM ticketToInvoice ti;
|
FROM tmp.ticketToInvoice ti;
|
||||||
|
|
||||||
CALL invoiceExpenceMake(vNewInvoiceId);
|
CALL invoiceExpenceMake(vNewInvoiceId);
|
||||||
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
||||||
|
@ -159,7 +159,7 @@ BEGIN
|
||||||
(KEY (ticketFk))
|
(KEY (ticketFk))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id ticketFk
|
SELECT id ticketFk
|
||||||
FROM ticketToInvoice;
|
FROM tmp.ticketToInvoice;
|
||||||
|
|
||||||
CALL `ticket_getTax`('NATIONAL');
|
CALL `ticket_getTax`('NATIONAL');
|
||||||
|
|
||||||
|
@ -220,6 +220,6 @@ BEGIN
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE `ticketToInvoice`;
|
DROP TEMPORARY TABLE `tmp`.`ticketToInvoice`;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES ('VnUser', '*', '*', 'ALLOW', 'ROLE', 'employee');
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (id, model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES ('VnUser', 'acl', 'READ', 'ALLOW', 'ROLE', 'account');
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (id, model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES ('VnUser', 'getCurrentUserData', 'READ', 'ALLOW', 'ROLE', 'account');
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (id, model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES ('VnUser', 'changePassword', '*', 'ALLOW', 'ROLE', 'account');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE `hedera`.`imageCollection` t
|
||||||
|
SET t.model = 'VnUser'
|
||||||
|
WHERE t.id = 6;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('Receipt', 'receiptEmail', '*', 'ALLOW', 'ROLE', 'salesAssistant');
|
|
@ -10,7 +10,7 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`(
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Creación de facturas emitidas.
|
* Creación de facturas emitidas.
|
||||||
* requiere previamente tabla ticketToInvoice(id).
|
* requiere previamente tabla tmp.ticketToInvoice(id).
|
||||||
*
|
*
|
||||||
* @param vSerial serie a la cual se hace la factura
|
* @param vSerial serie a la cual se hace la factura
|
||||||
* @param vInvoiceDate fecha de la factura
|
* @param vInvoiceDate fecha de la factura
|
||||||
|
@ -49,7 +49,7 @@ BEGIN
|
||||||
vCompanyFk,
|
vCompanyFk,
|
||||||
vMaxShipped,
|
vMaxShipped,
|
||||||
vIsCorrectInvoiceDate
|
vIsCorrectInvoiceDate
|
||||||
FROM ticketToInvoice tt
|
FROM tmp.ticketToInvoice tt
|
||||||
JOIN ticket t ON t.id = tt.id;
|
JOIN ticket t ON t.id = tt.id;
|
||||||
|
|
||||||
IF(vMaxShipped > vInvoiceDate) THEN
|
IF(vMaxShipped > vInvoiceDate) THEN
|
||||||
|
@ -60,9 +60,9 @@ BEGIN
|
||||||
CALL util.throw('Exists an invoice with a previous date');
|
CALL util.throw('Exists an invoice with a previous date');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Eliminem de ticketToInvoice els tickets que no han de ser facturats
|
-- Eliminem de tmp.ticketToInvoice els tickets que no han de ser facturats
|
||||||
DELETE ti.*
|
DELETE ti.*
|
||||||
FROM ticketToInvoice ti
|
FROM tmp.ticketToInvoice ti
|
||||||
JOIN ticket t ON t.id = ti.id
|
JOIN ticket t ON t.id = ti.id
|
||||||
JOIN sale s ON s.ticketFk = t.id
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
JOIN item i ON i.id = s.itemFk
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
@ -77,11 +77,11 @@ BEGIN
|
||||||
|
|
||||||
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100) <> 0
|
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100) <> 0
|
||||||
INTO vIsAnySaleToInvoice
|
INTO vIsAnySaleToInvoice
|
||||||
FROM ticketToInvoice t
|
FROM tmp.ticketToInvoice t
|
||||||
JOIN sale s ON s.ticketFk = t.id;
|
JOIN sale s ON s.ticketFk = t.id;
|
||||||
|
|
||||||
SELECT COUNT(*) > 0 INTO vIsAnyServiceToInvoice
|
SELECT COUNT(*) > 0 INTO vIsAnyServiceToInvoice
|
||||||
FROM ticketToInvoice t
|
FROM tmp.ticketToInvoice t
|
||||||
JOIN ticketService ts ON ts.ticketFk = t.id;
|
JOIN ticketService ts ON ts.ticketFk = t.id;
|
||||||
|
|
||||||
IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice)
|
IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice)
|
||||||
|
@ -121,13 +121,13 @@ BEGIN
|
||||||
WHERE id = vNewInvoiceId;
|
WHERE id = vNewInvoiceId;
|
||||||
|
|
||||||
UPDATE ticket t
|
UPDATE ticket t
|
||||||
JOIN ticketToInvoice ti ON ti.id = t.id
|
JOIN tmp.ticketToInvoice ti ON ti.id = t.id
|
||||||
SET t.refFk = vNewRef;
|
SET t.refFk = vNewRef;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
|
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
|
||||||
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
|
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
|
||||||
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
|
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
|
||||||
FROM ticketToInvoice ti
|
FROM tmp.ticketToInvoice ti
|
||||||
LEFT JOIN ticketState ts ON ti.id = ts.ticket
|
LEFT JOIN ticketState ts ON ti.id = ts.ticket
|
||||||
JOIN state s
|
JOIN state s
|
||||||
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
|
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
|
||||||
|
@ -137,7 +137,7 @@ BEGIN
|
||||||
|
|
||||||
INSERT INTO ticketLog (action, userFk, originFk, description)
|
INSERT INTO ticketLog (action, userFk, originFk, description)
|
||||||
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
||||||
FROM ticketToInvoice ti;
|
FROM tmp.ticketToInvoice ti;
|
||||||
|
|
||||||
CALL invoiceExpenceMake(vNewInvoiceId);
|
CALL invoiceExpenceMake(vNewInvoiceId);
|
||||||
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
||||||
|
@ -175,7 +175,7 @@ BEGIN
|
||||||
(KEY (ticketFk))
|
(KEY (ticketFk))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id ticketFk
|
SELECT id ticketFk
|
||||||
FROM ticketToInvoice;
|
FROM tmp.ticketToInvoice;
|
||||||
|
|
||||||
CALL `ticket_getTax`('NATIONAL');
|
CALL `ticket_getTax`('NATIONAL');
|
||||||
|
|
||||||
|
@ -253,6 +253,6 @@ BEGIN
|
||||||
DROP TEMPORARY TABLE tmp.ticketServiceTax;
|
DROP TEMPORARY TABLE tmp.ticketServiceTax;
|
||||||
END IF;
|
END IF;
|
||||||
END IF;
|
END IF;
|
||||||
DROP TEMPORARY TABLE `ticketToInvoice`;
|
DROP TEMPORARY TABLE tmp.`ticketToInvoice`;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -0,0 +1,16 @@
|
||||||
|
ALTER TABLE `vn`.`chat` ADD statusNew enum('pending','sent','error','sending') DEFAULT 'pending' NOT NULL;
|
||||||
|
|
||||||
|
UPDATE `vn`.`chat`
|
||||||
|
SET statusNew = 'pending'
|
||||||
|
WHERE status = 0;
|
||||||
|
|
||||||
|
UPDATE `vn`.`chat`
|
||||||
|
SET statusNew = 'sent'
|
||||||
|
WHERE status = 1;
|
||||||
|
|
||||||
|
UPDATE `vn`.`chat`
|
||||||
|
SET statusNew = 'error'
|
||||||
|
WHERE status = 2;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`chat` CHANGE status status__ tinyint(1) DEFAULT NULL NULL;
|
||||||
|
ALTER TABLE `vn`.`chat` CHANGE statusNew status enum('pending','sent','error','sending') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT 'pending' NOT NULL;
|
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE `vn`.`invoiceInConfig` ADD daysAgo INT UNSIGNED DEFAULT 45 COMMENT 'Días en el pasado para mostrar facturas en invoiceIn series en salix';
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('InvoiceIn', 'getSerial', 'READ', 'ALLOW', 'ROLE', 'administrative');
|
|
@ -0,0 +1,14 @@
|
||||||
|
ALTER TABLE `vn`.`itemType` ADD isFragile tinyint(1) NULL;
|
||||||
|
ALTER TABLE `vn`.`itemType` MODIFY COLUMN isFragile tinyint(1) DEFAULT 0 NOT NULL;
|
||||||
|
|
||||||
|
UPDATE `vn`.`itemType`
|
||||||
|
SET isFragile = 1
|
||||||
|
WHERE code IN ('ZKA', 'ZKE');
|
||||||
|
|
||||||
|
UPDATE `vn`.`itemType`
|
||||||
|
SET isFragile = 1
|
||||||
|
WHERE id IN (SELECT it.id
|
||||||
|
FROM `vn`.`itemCategory` ic
|
||||||
|
JOIN `vn`.`itemType` it ON it.categoryFk = ic.id
|
||||||
|
WHERE ic.code = 'plant');
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
INSERT INTO `salix`.`ACL` ( model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES('Mail', '*', '*', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,3 @@
|
||||||
|
DROP TRIGGER `vn`.`supplierAccount_afterInsert`;
|
||||||
|
DROP TRIGGER `vn`.`supplierAccount_afterUpdate`;
|
||||||
|
DROP TRIGGER `vn`.`supplierAccount_afterDelete`;
|
|
@ -0,0 +1,47 @@
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`ticket_getWarnings`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE PROCEDURE `vn`.`ticket_getWarnings`()
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Calcula las adventencias para un conjunto de tickets.
|
||||||
|
* Agrupados por ticket
|
||||||
|
*
|
||||||
|
* @table tmp.sale_getWarnings(ticketFk) Identificadores de los tickets a calcular
|
||||||
|
* @return tmp.ticket_warnings
|
||||||
|
*/
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.sale_warnings;
|
||||||
|
CREATE TEMPORARY TABLE tmp.sale_warnings (
|
||||||
|
ticketFk INT(11),
|
||||||
|
saleFk INT(11),
|
||||||
|
isFragile INTEGER(1) DEFAULT 0,
|
||||||
|
PRIMARY KEY (ticketFk, saleFk)
|
||||||
|
) ENGINE = MEMORY;
|
||||||
|
|
||||||
|
-- Frágil
|
||||||
|
INSERT INTO tmp.sale_warnings(ticketFk, saleFk, isFragile)
|
||||||
|
SELECT tt.ticketFk, s.id, TRUE
|
||||||
|
FROM tmp.sale_getWarnings tt
|
||||||
|
LEFT JOIN sale s ON s.ticketFk = tt.ticketFk
|
||||||
|
LEFT JOIN item i ON i.id = s.itemFk
|
||||||
|
LEFT JOIN itemType it ON it.id = i.typeFk
|
||||||
|
LEFT JOIN agencyMode am ON am.id = tt.agencyModeFk
|
||||||
|
LEFT JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
|
||||||
|
WHERE dm.code IN ('AGENCY')
|
||||||
|
AND it.isFragile;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_warnings;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticket_warnings
|
||||||
|
(PRIMARY KEY (ticketFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT
|
||||||
|
sw.ticketFk,
|
||||||
|
MAX(sw.isFragile) AS isFragile
|
||||||
|
FROM tmp.sale_warnings sw
|
||||||
|
GROUP BY sw.ticketFk;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE
|
||||||
|
tmp.sale_warnings;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,72 @@
|
||||||
|
CREATE TABLE `vn`.`wagonType` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(30) NOT NULL UNIQUE,
|
||||||
|
`divisible` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3;
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`wagonTypeColor` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(30) NOT NULL UNIQUE,
|
||||||
|
`rgb` varchar(30) NOT NULL UNIQUE,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3;
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`wagonTypeTray` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`typeFk` int(11) unsigned,
|
||||||
|
`height` int(11) unsigned NOT NULL,
|
||||||
|
`colorFk` int(11) unsigned,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY (`typeFk`,`height`),
|
||||||
|
CONSTRAINT `wagonTypeTray_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `wagonTypeTray_color` FOREIGN KEY (`colorFk`) REFERENCES `wagonTypeColor` (`id`) ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3;
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`wagonConfig` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`width` int(11) unsigned DEFAULT 1350,
|
||||||
|
`height` int(11) unsigned DEFAULT 1900,
|
||||||
|
`maxWagonHeight` int(11) unsigned DEFAULT 200,
|
||||||
|
`minHeightBetweenTrays` int(11) unsigned DEFAULT 50,
|
||||||
|
`maxTrays` int(11) unsigned DEFAULT 6,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3;
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`collectionWagon` (
|
||||||
|
`collectionFk` int(11) NOT NULL,
|
||||||
|
`wagonFk` int(11) NOT NULL,
|
||||||
|
`position` int(11) unsigned,
|
||||||
|
PRIMARY KEY (`collectionFk`,`position`),
|
||||||
|
UNIQUE KEY `collectionWagon_unique` (`collectionFk`,`wagonFk`),
|
||||||
|
CONSTRAINT `collectionWagon_collection` FOREIGN KEY (`collectionFk`) REFERENCES `collection` (`id`) ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `collectionWagon_wagon` FOREIGN KEY (`wagonFk`) REFERENCES `wagon` (`id`) ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`collectionWagonTicket` (
|
||||||
|
`ticketFk` int(11) NOT NULL,
|
||||||
|
`wagonFk` int(11) NOT NULL,
|
||||||
|
`trayFk` int(11) unsigned NOT NULL,
|
||||||
|
`side` SET('L', 'R') NULL,
|
||||||
|
PRIMARY KEY (`ticketFk`),
|
||||||
|
CONSTRAINT `collectionWagonTicket_ticket` FOREIGN KEY (`ticketFk`) REFERENCES `ticket` (`id`) ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `collectionWagonTicket_wagon` FOREIGN KEY (`wagonFk`) REFERENCES `wagon` (`id`) ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `collectionWagonTicket_tray` FOREIGN KEY (`trayFk`) REFERENCES `wagonTypeTray` (`id`) ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned NOT NULL;
|
||||||
|
ALTER TABLE `vn`.`wagon` ADD `label` int(11) unsigned NOT NULL;
|
||||||
|
ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('WagonType', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('WagonTypeColor', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('WagonTypeTray', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('WagonConfig', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('CollectionWagon', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('CollectionWagonTicket', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('Wagon', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi');
|
|
@ -0,0 +1,74 @@
|
||||||
|
DROP TABLE `vn`.`dmsRecover`;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`delivery` DROP FOREIGN KEY delivery_FK;
|
||||||
|
ALTER TABLE `vn`.`delivery` DROP COLUMN addressFk;
|
||||||
|
ALTER TABLE `vn`.`delivery` ADD ticketFk INT NOT NULL;
|
||||||
|
ALTER TABLE `vn`.`delivery` ADD CONSTRAINT delivery_ticketFk_FK FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`);
|
||||||
|
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE `property` = 'saveSign';
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`)
|
||||||
|
VALUES
|
||||||
|
('Ticket','saveSign','WRITE','ALLOW','employee');
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS vn.route_getTickets;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`route_getTickets`(vRouteFk INT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Pasado un RouteFk devuelve la información
|
||||||
|
* de sus tickets.
|
||||||
|
*
|
||||||
|
* @param vRouteFk
|
||||||
|
*
|
||||||
|
* @select Información de los tickets
|
||||||
|
*/
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
t.id Id,
|
||||||
|
t.clientFk Client,
|
||||||
|
a.id Address,
|
||||||
|
t.packages Packages,
|
||||||
|
a.street AddressName,
|
||||||
|
a.postalCode PostalCode,
|
||||||
|
a.city City,
|
||||||
|
sub2.itemPackingTypeFk PackingType,
|
||||||
|
c.phone ClientPhone,
|
||||||
|
c.mobile ClientMobile,
|
||||||
|
a.phone AddressPhone,
|
||||||
|
a.mobile AddressMobile,
|
||||||
|
d.longitude Longitude,
|
||||||
|
d.latitude Latitude,
|
||||||
|
wm.mediaValue SalePersonPhone,
|
||||||
|
tob.Note Note,
|
||||||
|
t.isSigned Signed
|
||||||
|
FROM ticket t
|
||||||
|
JOIN client c ON t.clientFk = c.id
|
||||||
|
JOIN address a ON t.addressFk = a.id
|
||||||
|
LEFT JOIN delivery d ON t.id = d.ticketFk
|
||||||
|
LEFT JOIN workerMedia wm ON wm.workerFk = c.salesPersonFk
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT tob.description Note, t.id
|
||||||
|
FROM ticketObservation tob
|
||||||
|
JOIN ticket t ON tob.ticketFk = t.id
|
||||||
|
JOIN observationType ot ON ot.id = tob.observationTypeFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
AND ot.code = 'delivery'
|
||||||
|
)tob ON tob.id = t.id
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT sub.ticketFk,
|
||||||
|
CONCAT('(', GROUP_CONCAT(DISTINCT sub.itemPackingTypeFk ORDER BY sub.items DESC SEPARATOR ','), ') ') itemPackingTypeFk
|
||||||
|
FROM (SELECT s.ticketFk , i.itemPackingTypeFk, COUNT(*) items
|
||||||
|
FROM ticket t
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id,i.itemPackingTypeFk)sub
|
||||||
|
GROUP BY sub.ticketFk
|
||||||
|
) sub2 ON sub2.ticketFk = t.id
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id
|
||||||
|
ORDER BY t.priority;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,67 @@
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE `property` = 'saveSign';
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`)
|
||||||
|
VALUES
|
||||||
|
('Ticket','saveSign','WRITE','ALLOW','employee');
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS vn.route_getTickets;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`route_getTickets`(vRouteFk INT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Pasado un RouteFk devuelve la información
|
||||||
|
* de sus tickets.
|
||||||
|
*
|
||||||
|
* @param vRouteFk
|
||||||
|
*
|
||||||
|
* @select Información de los tickets
|
||||||
|
*/
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
t.id Id,
|
||||||
|
t.clientFk Client,
|
||||||
|
a.id Address,
|
||||||
|
t.packages Packages,
|
||||||
|
a.street AddressName,
|
||||||
|
a.postalCode PostalCode,
|
||||||
|
a.city City,
|
||||||
|
sub2.itemPackingTypeFk PackingType,
|
||||||
|
c.phone ClientPhone,
|
||||||
|
c.mobile ClientMobile,
|
||||||
|
a.phone AddressPhone,
|
||||||
|
a.mobile AddressMobile,
|
||||||
|
d.longitude Longitude,
|
||||||
|
d.latitude Latitude,
|
||||||
|
wm.mediaValue SalePersonPhone,
|
||||||
|
tob.Note Note,
|
||||||
|
t.isSigned Signed
|
||||||
|
FROM ticket t
|
||||||
|
JOIN client c ON t.clientFk = c.id
|
||||||
|
JOIN address a ON t.addressFk = a.id
|
||||||
|
LEFT JOIN delivery d ON t.id = d.ticketFk
|
||||||
|
LEFT JOIN workerMedia wm ON wm.workerFk = c.salesPersonFk
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT tob.description Note, t.id
|
||||||
|
FROM ticketObservation tob
|
||||||
|
JOIN ticket t ON tob.ticketFk = t.id
|
||||||
|
JOIN observationType ot ON ot.id = tob.observationTypeFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
AND ot.code = 'delivery'
|
||||||
|
)tob ON tob.id = t.id
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT sub.ticketFk,
|
||||||
|
CONCAT('(', GROUP_CONCAT(DISTINCT sub.itemPackingTypeFk ORDER BY sub.items DESC SEPARATOR ','), ') ') itemPackingTypeFk
|
||||||
|
FROM (SELECT s.ticketFk , i.itemPackingTypeFk, COUNT(*) items
|
||||||
|
FROM ticket t
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id,i.itemPackingTypeFk)sub
|
||||||
|
GROUP BY sub.ticketFk
|
||||||
|
) sub2 ON sub2.ticketFk = t.id
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id
|
||||||
|
ORDER BY t.priority;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,83 @@
|
||||||
|
CREATE TABLE `vn`.`dmsRecover` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`ticketFk` int(11) DEFAULT NULL,
|
||||||
|
`sign` text DEFAULT NULL,
|
||||||
|
`created` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `ticketFk_idx` (`ticketFk`),
|
||||||
|
CONSTRAINT `ticketFk` FOREIGN KEY (`ticketFk`) REFERENCES `ticket` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=31917 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`delivery` ADD addressFk INT;
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`route_getTickets`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`route_getTickets`(vRouteFk INT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Pasado un RouteFk devuelve la información
|
||||||
|
* de sus tickets.
|
||||||
|
*
|
||||||
|
* @param vRouteFk
|
||||||
|
* @select Información de los tickets
|
||||||
|
*/
|
||||||
|
SELECT *
|
||||||
|
FROM (
|
||||||
|
SELECT t.id Id,
|
||||||
|
t.clientFk Client,
|
||||||
|
a.id Address,
|
||||||
|
a.nickname ClientName,
|
||||||
|
t.packages Packages,
|
||||||
|
a.street AddressName,
|
||||||
|
a.postalCode PostalCode,
|
||||||
|
a.city City,
|
||||||
|
sub2.itemPackingTypeFk PackingType,
|
||||||
|
c.phone ClientPhone,
|
||||||
|
c.mobile ClientMobile,
|
||||||
|
a.phone AddressPhone,
|
||||||
|
a.mobile AddressMobile,
|
||||||
|
d.longitude Longitude,
|
||||||
|
d.latitude Latitude,
|
||||||
|
wm.mediaValue SalePersonPhone,
|
||||||
|
tob.description Note,
|
||||||
|
t.isSigned Signed,
|
||||||
|
t.priority
|
||||||
|
FROM ticket t
|
||||||
|
JOIN client c ON t.clientFk = c.id
|
||||||
|
JOIN address a ON t.addressFk = a.id
|
||||||
|
LEFT JOIN delivery d ON d.addressFk = a.id
|
||||||
|
LEFT JOIN workerMedia wm ON wm.workerFk = c.salesPersonFk
|
||||||
|
LEFT JOIN(
|
||||||
|
SELECT tob.description, t.id
|
||||||
|
FROM ticketObservation tob
|
||||||
|
JOIN ticket t ON tob.ticketFk = t.id
|
||||||
|
JOIN observationType ot ON ot.id = tob.observationTypeFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
AND ot.code = 'delivery'
|
||||||
|
)tob ON tob.id = t.id
|
||||||
|
LEFT JOIN(
|
||||||
|
SELECT sub.ticketFk,
|
||||||
|
CONCAT('(',
|
||||||
|
GROUP_CONCAT(DISTINCT sub.itemPackingTypeFk
|
||||||
|
ORDER BY sub.items DESC SEPARATOR ','),
|
||||||
|
') ') itemPackingTypeFk
|
||||||
|
FROM (
|
||||||
|
SELECT s.ticketFk, i.itemPackingTypeFk, COUNT(*) items
|
||||||
|
FROM ticket t
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id, i.itemPackingTypeFk
|
||||||
|
)sub
|
||||||
|
GROUP BY sub.ticketFk
|
||||||
|
)sub2 ON sub2.ticketFk = t.id
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
ORDER BY d.id DESC
|
||||||
|
LIMIT 10000000000000000000
|
||||||
|
)sub3
|
||||||
|
GROUP BY sub3.id
|
||||||
|
ORDER BY sub3.priority;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE `vn`.`printQueueArgs` MODIFY COLUMN value varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL;
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TRIGGER IF EXISTS `vn`.`claimBeginning_afterInsert`;
|
|
@ -0,0 +1,72 @@
|
||||||
|
DROP TRIGGER IF EXISTS `vn`.`client_beforeUpdate`;
|
||||||
|
USE `vn`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `client`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
DECLARE vText VARCHAR(255) DEFAULT NULL;
|
||||||
|
DECLARE vPayMethodFk INT;
|
||||||
|
-- Comprueba que el formato de los teléfonos es válido
|
||||||
|
|
||||||
|
IF !(NEW.phone <=> OLD.phone) AND (NEW.phone <> '') THEN
|
||||||
|
CALL pbx.phone_isValid(NEW.phone);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF !(NEW.mobile <=> OLD.mobile) AND (NEW.mobile <> '')THEN
|
||||||
|
CALL pbx.phone_isValid(NEW.mobile);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT id INTO vPayMethodFk
|
||||||
|
FROM vn.payMethod
|
||||||
|
WHERE code = 'bankDraft';
|
||||||
|
|
||||||
|
IF NEW.payMethodFk = vPayMethodFk AND NEW.dueDay = 0 THEN
|
||||||
|
SET NEW.dueDay = 5;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Avisar al comercial si ha llegado la documentación sepa/core
|
||||||
|
|
||||||
|
IF NEW.hasSepaVnl AND !OLD.hasSepaVnl THEN
|
||||||
|
SET vText = 'Sepa de VNL';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF NEW.hasCoreVnl AND !OLD.hasCoreVnl THEN
|
||||||
|
SET vText = 'Core de VNL';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF vText IS NOT NULL
|
||||||
|
THEN
|
||||||
|
INSERT INTO mail(receiver, replyTo, `subject`, body)
|
||||||
|
SELECT
|
||||||
|
CONCAT(IF(ac.id,u.name, 'jgallego'), '@verdnatura.es'),
|
||||||
|
'administracion@verdnatura.es',
|
||||||
|
CONCAT('Cliente ', NEW.id),
|
||||||
|
CONCAT('Recibida la documentación: ', vText)
|
||||||
|
FROM worker w
|
||||||
|
LEFT JOIN account.user u ON w.userFk = u.id AND u.active
|
||||||
|
LEFT JOIN account.account ac ON ac.id = u.id
|
||||||
|
WHERE w.id = NEW.salesPersonFk;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF NEW.salespersonFk IS NULL AND OLD.salespersonFk IS NOT NULL THEN
|
||||||
|
IF (SELECT COUNT(clientFk)
|
||||||
|
FROM clientProtected
|
||||||
|
WHERE clientFk = NEW.id
|
||||||
|
) > 0 THEN
|
||||||
|
CALL util.throw("HAS_CLIENT_PROTECTED");
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF !(NEW.salesPersonFk <=> OLD.salesPersonFk) THEN
|
||||||
|
SET NEW.lastSalesPersonFk = IFNULL(NEW.salesPersonFk, OLD.salesPersonFk);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF !(NEW.businessTypeFk <=> OLD.businessTypeFk) AND (NEW.businessTypeFk = 'individual' OR OLD.businessTypeFk = 'individual') THEN
|
||||||
|
SET NEW.isTaxDataChecked = 0;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,5 @@
|
||||||
|
DROP TRIGGER `vn`.`deviceProduction_afterInsert`;
|
||||||
|
DROP TRIGGER `vn`.`deviceProduction_afterUpdate`;
|
||||||
|
|
||||||
|
DROP TRIGGER `vn`.`deviceProductionUser_afterDelete`;
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
DROP TABLE IF EXISTS `vn`.`dmsRecover`;
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`route_getTickets`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`route_getTickets`(vRouteFk INT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Pasado un RouteFk devuelve la información
|
||||||
|
* de sus tickets.
|
||||||
|
*
|
||||||
|
* @param vRouteFk
|
||||||
|
* @select Información de los tickets
|
||||||
|
*/
|
||||||
|
SELECT *
|
||||||
|
FROM (
|
||||||
|
SELECT t.id Id,
|
||||||
|
t.clientFk Client,
|
||||||
|
a.id Address,
|
||||||
|
a.nickname ClientName,
|
||||||
|
t.packages Packages,
|
||||||
|
a.street AddressName,
|
||||||
|
a.postalCode PostalCode,
|
||||||
|
a.city City,
|
||||||
|
sub2.itemPackingTypeFk PackingType,
|
||||||
|
c.phone ClientPhone,
|
||||||
|
c.mobile ClientMobile,
|
||||||
|
a.phone AddressPhone,
|
||||||
|
a.mobile AddressMobile,
|
||||||
|
d.longitude Longitude,
|
||||||
|
d.latitude Latitude,
|
||||||
|
wm.mediaValue SalePersonPhone,
|
||||||
|
tob.description Note,
|
||||||
|
t.isSigned Signed,
|
||||||
|
t.priority
|
||||||
|
FROM ticket t
|
||||||
|
JOIN client c ON t.clientFk = c.id
|
||||||
|
JOIN address a ON t.addressFk = a.id
|
||||||
|
LEFT JOIN delivery d ON d.ticketFk = t.id
|
||||||
|
LEFT JOIN workerMedia wm ON wm.workerFk = c.salesPersonFk
|
||||||
|
LEFT JOIN(
|
||||||
|
SELECT tob.description, t.id
|
||||||
|
FROM ticketObservation tob
|
||||||
|
JOIN ticket t ON tob.ticketFk = t.id
|
||||||
|
JOIN observationType ot ON ot.id = tob.observationTypeFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
AND ot.code = 'delivery'
|
||||||
|
)tob ON tob.id = t.id
|
||||||
|
LEFT JOIN(
|
||||||
|
SELECT sub.ticketFk,
|
||||||
|
CONCAT('(',
|
||||||
|
GROUP_CONCAT(DISTINCT sub.itemPackingTypeFk
|
||||||
|
ORDER BY sub.items DESC SEPARATOR ','),
|
||||||
|
') ') itemPackingTypeFk
|
||||||
|
FROM (
|
||||||
|
SELECT s.ticketFk, i.itemPackingTypeFk, COUNT(*) items
|
||||||
|
FROM ticket t
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id, i.itemPackingTypeFk
|
||||||
|
)sub
|
||||||
|
GROUP BY sub.ticketFk
|
||||||
|
)sub2 ON sub2.ticketFk = t.id
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
ORDER BY d.id DESC
|
||||||
|
LIMIT 10000000000000000000
|
||||||
|
)sub3
|
||||||
|
GROUP BY sub3.id
|
||||||
|
ORDER BY sub3.priority;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`delivery` DROP FOREIGN KEY delivery_ticketFk_FK;
|
||||||
|
ALTER TABLE `vn`.`delivery` DROP COLUMN ticketFk;
|
||||||
|
ALTER TABLE `vn`.`delivery` ADD ticketFk INT DEFAULT NULL;
|
||||||
|
ALTER TABLE `vn`.`delivery` ADD CONSTRAINT delivery_ticketFk_FK FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`);
|
|
@ -0,0 +1,13 @@
|
||||||
|
DROP TRIGGER IF EXISTS `vn`.`invoiceOut_afterInsert`;
|
||||||
|
USE vn;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`invoiceOut_afterInsert`
|
||||||
|
AFTER INSERT ON `invoiceOut`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
CALL clientRisk_update(NEW.clientFk, NEW.companyFk, NEW.amount);
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('InvoiceIn', 'negativeBases', 'READ', 'ALLOW', 'ROLE', 'administrative'),
|
||||||
|
('InvoiceIn', 'negativeBasesCsv', 'READ', 'ALLOW', 'ROLE', 'administrative');
|
|
@ -0,0 +1,14 @@
|
||||||
|
CREATE TABLE `vn`.`workerObservation` (
|
||||||
|
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`workerFk` int(10) unsigned DEFAULT NULL,
|
||||||
|
`userFk` int(10) unsigned DEFAULT NULL,
|
||||||
|
`text` text COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||||
|
`created` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
CONSTRAINT `workerFk_workerObservation_FK` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `userFk_workerObservation_FK` FOREIGN KEY (`userFk`) REFERENCES `account`.`user`(`id`) ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Todas las observaciones referentes a un trabajador';
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('WorkerObservation', '*', '*', 'ALLOW', 'ROLE', 'hr');
|
|
@ -0,0 +1,3 @@
|
||||||
|
UPDATE `salix`.`ACL`
|
||||||
|
SET model = 'InvoiceOut'
|
||||||
|
WHERE property IN ('negativeBases', 'negativeBasesCsv');
|
|
@ -0,0 +1,3 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES ('ClientInforma', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('ClientInforma', '*', 'WRITE', 'ALLOW', 'ROLE', 'financial');
|
|
@ -0,0 +1,16 @@
|
||||||
|
ALTER TABLE `vn`.`client` ADD rating INT UNSIGNED DEFAULT NULL NULL COMMENT 'información proporcionada por Informa';
|
||||||
|
ALTER TABLE `vn`.`client` ADD recommendedCredit INT UNSIGNED DEFAULT NULL NULL COMMENT 'información proporcionada por Informa';
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`clientInforma` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`clientFk` int(11) NOT NULL,
|
||||||
|
`rating` int(10) unsigned DEFAULT NULL,
|
||||||
|
`recommendedCredit` int(10) unsigned DEFAULT NULL,
|
||||||
|
`workerFk` int(10) unsigned NOT NULL,
|
||||||
|
`created` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `informaWorkers_fk_idx` (`workerFk`),
|
||||||
|
KEY `informaClientFk` (`clientFk`),
|
||||||
|
CONSTRAINT `informa_ClienteFk` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `informa_workers_fk` FOREIGN KEY (`workerFk`) REFERENCES `worker` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='información proporcionada por Informa, se actualiza desde el hook de client (salix)';
|
|
@ -0,0 +1,64 @@
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE id=7;
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('Client', 'setRating', 'WRITE', 'ALLOW', 'ROLE', 'financial');
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('Client', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'addressesPropagateRe', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'canBeInvoiced', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'canCreateTicket', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'consumption', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'createAddress', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'createWithUser', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'extendedListFilter', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'getAverageInvoiced', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'getCard', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'getDebt', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'getMana', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'transactions', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'hasCustomerRole', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'isValidClient', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'lastActiveTickets', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'sendSms', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'setPassword', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'summary', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'updateAddress', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'updateFiscalData', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'updateUser', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'uploadFile', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'campaignMetricsPdf', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'campaignMetricsEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'clientWelcomeHtml', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'clientWelcomeEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'printerSetupHtml', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'printerSetupEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'sepaCoreEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'letterDebtorPdf', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'letterDebtorStHtml', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'letterDebtorStEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'letterDebtorNdHtml', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'letterDebtorNdEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'clientDebtStatementPdf', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'clientDebtStatementHtml', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'clientDebtStatementEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'creditRequestPdf', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'creditRequestHtml', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'creditRequestEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'incotermsAuthorizationPdf', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'incotermsAuthorizationHtml', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'incotermsAuthorizationEmail', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'consumptionSendQueued', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'filter', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'getClientOrSupplierReference', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'upsert', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'create', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'replaceById', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'updateAttributes', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'updateAttributes', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'deleteById', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'replaceOrCreate', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'updateAll', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'upsertWithWhere', '*', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,2 @@
|
||||||
|
DROP PROCEDURE `vn`.`refund`;
|
||||||
|
DROP PROCEDURE `vn`.`ticket_doRefund`;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE `vn`.`entry` DROP COLUMN `notes`;
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- vn.companyI18n definition
|
||||||
|
CREATE TABLE `vn`.`companyI18n` (
|
||||||
|
`companyFk` smallint(5) unsigned NOT NULL,
|
||||||
|
`lang` char(2) CHARACTER SET utf8mb3 NOT NULL,
|
||||||
|
`footnotes` longtext COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`companyFk`,`lang`),
|
||||||
|
CONSTRAINT `companyI18n_FK` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE `vn`.`company` ADD `web` varchar(100) NULL;
|
|
@ -0,0 +1,3 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('Defaulter', 'observationEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,77 @@
|
||||||
|
CREATE OR REPLACE
|
||||||
|
ALGORITHM = UNDEFINED VIEW `vn`.`zoneEstimatedDelivery` AS
|
||||||
|
select
|
||||||
|
`t`.`zoneFk` AS `zoneFk`,
|
||||||
|
cast(`util`.`VN_CURDATE`() + interval hour(ifnull(`zc`.`hour`, `z`.`hour`)) * 60 + minute(ifnull(`zc`.`hour`, `z`.`hour`)) minute as time) AS `hourTheoretical`,
|
||||||
|
cast(sum(`sv`.`volume`) as decimal(5, 1)) AS `totalVolume`,
|
||||||
|
cast(sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) as decimal(5, 1)) AS `remainingVolume`,
|
||||||
|
greatest(
|
||||||
|
ifnull(`lhp`.`m3`, 0),
|
||||||
|
ifnull(`dl`.`minSpeed`, 0)
|
||||||
|
) AS `speed`,
|
||||||
|
cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `hourEffective`,
|
||||||
|
floor(-sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0))) AS `minutesLess`,
|
||||||
|
cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `etc`
|
||||||
|
from
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
`vn`.`ticket` `t`
|
||||||
|
join `vn`.`ticketStateToday` `tst` on
|
||||||
|
(
|
||||||
|
`tst`.`ticket` = `t`.`id`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
join `vn`.`state` `s` on
|
||||||
|
(
|
||||||
|
`s`.`id` = `tst`.`state`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
join `vn`.`saleVolume` `sv` on
|
||||||
|
(
|
||||||
|
`sv`.`ticketFk` = `t`.`id`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
left join `vn`.`lastHourProduction` `lhp` on
|
||||||
|
(
|
||||||
|
`lhp`.`warehouseFk` = `t`.`warehouseFk`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
join `vn`.`warehouse` `w` on
|
||||||
|
(
|
||||||
|
`w`.`id` = `t`.`warehouseFk`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
join `vn`.`warehouseAlias` `wa` on
|
||||||
|
(
|
||||||
|
`wa`.`id` = `w`.`aliasFk`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
straight_join `vn`.`zone` `z` on
|
||||||
|
(
|
||||||
|
`z`.`id` = `t`.`zoneFk`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
left join `vn`.`zoneClosure` `zc` on
|
||||||
|
(
|
||||||
|
`zc`.`zoneFk` = `t`.`zoneFk`
|
||||||
|
and `zc`.`dated` = `util`.`VN_CURDATE`()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
left join `cache`.`departure_limit` `dl` on
|
||||||
|
(
|
||||||
|
`dl`.`warehouse_id` = `t`.`warehouseFk`
|
||||||
|
and `dl`.`fecha` = `util`.`VN_CURDATE`()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
where
|
||||||
|
`w`.`hasProduction` <> 0
|
||||||
|
and cast(`t`.`shipped` as date) = `util`.`VN_CURDATE`()
|
||||||
|
group by
|
||||||
|
`t`.`zoneFk`;
|
|
@ -0,0 +1,5 @@
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`sale_setQuantity`;
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`collection_updateSale`;
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`replaceMovimientosMark`;
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`saleTracking_Replace`;
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`sale_updateOriginalQuantity`;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE `vn`.`ticketConfig` ADD daysForWarningClaim INT DEFAULT 2 NOT NULL COMMENT 'dias restantes hasta que salte el aviso de reclamación fuera de plazo';
|
|
@ -0,0 +1,5 @@
|
||||||
|
UPDATE `vn`.`supplier` s
|
||||||
|
JOIN `vn`.`country` c ON c.id = s.countryFk
|
||||||
|
SET s.nif = MID(REPLACE(s.nif, ' ', ''), 3, LENGTH(REPLACE(s.nif, ' ', '')) - 1)
|
||||||
|
WHERE s.isVies = TRUE
|
||||||
|
AND c.code = LEFT(REPLACE(s.nif, ' ', ''), 2);
|
|
@ -0,0 +1,5 @@
|
||||||
|
UPDATE IGNORE `vn`.`client` c
|
||||||
|
JOIN `vn`.`country` co ON co.id = c.countryFk
|
||||||
|
SET c.fi = MID(REPLACE(c.fi, ' ', ''), 3, LENGTH(REPLACE(c.fi, ' ', '')) - 1)
|
||||||
|
WHERE c.isVies = TRUE
|
||||||
|
AND co.code = LEFT(REPLACE(c.fi, ' ', ''), 2);
|
|
@ -0,0 +1,21 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('VnUser', '*', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('VnUser','acl','READ','ALLOW','ROLE','account'),
|
||||||
|
('VnUser','getCurrentUserData','READ','ALLOW','ROLE','account'),
|
||||||
|
('VnUser','changePassword', 'WRITE', 'ALLOW', 'ROLE', 'account'),
|
||||||
|
('Account','exists','READ','ALLOW','ROLE','account');
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('Account','exists','READ','ALLOW','ROLE','account');
|
||||||
|
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE (model, property) = ('Account', 'acl');
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE (model, property) = ('Account', 'getCurrentUserData');
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE (model, property) = ('Account', 'changePassword');
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE model = 'UserAccount';
|
||||||
|
|
||||||
|
UPDATE `hedera`.`imageCollection` t
|
||||||
|
SET t.model = 'VnUser'
|
||||||
|
WHERE t.id = 6;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('UserLog', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('RoleLog', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
|
@ -98,20 +98,20 @@ INSERT INTO `hedera`.`tpvConfig`(`id`, `currency`, `terminal`, `transactionType`
|
||||||
VALUES
|
VALUES
|
||||||
(1, 978, 1, 0, 2000, 9, 0);
|
(1, 978, 1, 0, 2000, 9, 0);
|
||||||
|
|
||||||
INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,`email`,`lang`, `image`)
|
INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `bcryptPassword`, `password`,`role`,`active`,`email`,`lang`, `image`)
|
||||||
VALUES
|
VALUES
|
||||||
(1101, 'BruceWayne', 'Bruce Wayne', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1101, 'BruceWayne', 'Bruce Wayne', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1102, 'PetterParker', 'Petter Parker', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1102, 'PetterParker', 'Petter Parker', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1103, 'ClarkKent', 'Clark Kent', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@mydomain.com', 'fr', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1103, 'ClarkKent', 'Clark Kent', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@mydomain.com', 'fr', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1104, 'TonyStark', 'Tony Stark', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1104, 'TonyStark', 'Tony Stark', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@mydomain.com', 'es', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1105, 'MaxEisenhardt', 'Max Eisenhardt', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1105, 'MaxEisenhardt', 'Max Eisenhardt', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1106, 'DavidCharlesHaller', 'David Charles Haller', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1106, 'DavidCharlesHaller', 'David Charles Haller', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1107, 'HankPym', 'Hank Pym', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1107, 'HankPym', 'Hank Pym', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1108, 'CharlesXavier', 'Charles Xavier', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'CharlesXavier@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1108, 'CharlesXavier', 'Charles Xavier', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'CharlesXavier@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1109, 'BruceBanner', 'Bruce Banner', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'BruceBanner@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
(1109, 'BruceBanner', 'Bruce Banner', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'BruceBanner@mydomain.com', 'en', 'e7723f0b24ff05b32ed09d95196f2f29'),
|
||||||
(1110, 'JessicaJones', 'Jessica Jones', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'JessicaJones@mydomain.com', 'en', NULL),
|
(1110, 'JessicaJones', 'Jessica Jones', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'JessicaJones@mydomain.com', 'en', NULL),
|
||||||
(1111, 'Missing', 'Missing', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL),
|
(1111, 'Missing', 'Missing', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL),
|
||||||
(1112, 'Trash', 'Trash', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL);
|
(1112, 'Trash', 'Trash', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en', NULL);
|
||||||
|
|
||||||
INSERT INTO `account`.`mailAlias`(`id`, `alias`, `description`, `isPublic`)
|
INSERT INTO `account`.`mailAlias`(`id`, `alias`, `description`, `isPublic`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -173,10 +173,6 @@ INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPrepare
|
||||||
(1, 'First sector', 1, 1, 'FIRST'),
|
(1, 'First sector', 1, 1, 'FIRST'),
|
||||||
(2, 'Second sector', 2, 0, 'SECOND');
|
(2, 'Second sector', 2, 0, 'SECOND');
|
||||||
|
|
||||||
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
|
|
||||||
VALUES ('1106', '1', '1', 'H', '1', '1', '1'),
|
|
||||||
('1107', '1', '1', 'V', '1', '2', '1');
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAddress`)
|
INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAddress`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'printer1', 'path1', 0, 1 , NULL),
|
(1, 'printer1', 'path1', 0, 1 , NULL),
|
||||||
|
@ -501,7 +497,8 @@ INSERT INTO `vn`.`observationType`(`id`,`description`, `code`)
|
||||||
(3, 'Delivery', 'delivery'),
|
(3, 'Delivery', 'delivery'),
|
||||||
(4, 'SalesPerson', 'salesPerson'),
|
(4, 'SalesPerson', 'salesPerson'),
|
||||||
(5, 'Administrative', 'administrative'),
|
(5, 'Administrative', 'administrative'),
|
||||||
(6, 'Weight', 'weight');
|
(6, 'Weight', 'weight'),
|
||||||
|
(7, 'InvoiceOut', 'invoiceOut');
|
||||||
|
|
||||||
INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`)
|
INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -549,7 +546,8 @@ INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, util.VN_CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'),
|
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, util.VN_CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'),
|
||||||
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, util.VN_CURDATE(), 1, 'supplier address 2', 'GOTHAM', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1, '400664487V'),
|
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, util.VN_CURDATE(), 1, 'supplier address 2', 'GOTHAM', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1, '400664487V'),
|
||||||
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, util.VN_CURDATE(), 1, 'supplier address 3', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V');
|
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, util.VN_CURDATE(), 1, 'supplier address 3', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'),
|
||||||
|
(1381, 'Ornamentales', 'Ornamentales', 7185000440, 1, '03815934E', 0, util.VN_CURDATE(), 1, 'supplier address 4', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V');
|
||||||
|
|
||||||
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
|
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -738,7 +736,9 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
|
||||||
(9, 23, 5, 'care with the dog'),
|
(9, 23, 5, 'care with the dog'),
|
||||||
(10, 23, 4, 'Reclama ticket: 8'),
|
(10, 23, 4, 'Reclama ticket: 8'),
|
||||||
(11, 24, 4, 'Reclama ticket: 7'),
|
(11, 24, 4, 'Reclama ticket: 7'),
|
||||||
(12, 11, 3, 'Delivery after 10am');
|
(12, 11, 3, 'Delivery after 10am'),
|
||||||
|
(13, 1, 7, 'observation of ticket one'),
|
||||||
|
(14, 2, 7, 'observation of ticket two');
|
||||||
|
|
||||||
-- FIX for state hours on local, inter_afterInsert
|
-- FIX for state hours on local, inter_afterInsert
|
||||||
-- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND);
|
-- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND);
|
||||||
|
@ -838,14 +838,14 @@ INSERT INTO `vn`.`temperature`(`code`, `name`, `description`)
|
||||||
('warm', 'Warm', 'Warm'),
|
('warm', 'Warm', 'Warm'),
|
||||||
('cool', 'Cool', 'Cool');
|
('cool', 'Cool', 'Cool');
|
||||||
|
|
||||||
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`)
|
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`, `isFragile`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool'),
|
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool', 0),
|
||||||
(2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool'),
|
(2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool', 1),
|
||||||
(3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool'),
|
(3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool', 0),
|
||||||
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm'),
|
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm', 0),
|
||||||
(5, 'CON', 'Container', 3, NULL, 35, 1, 'warm'),
|
(5, 'CON', 'Container', 3, NULL, 35, 1, 'warm', 0),
|
||||||
(6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm');
|
(6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm', 1);
|
||||||
|
|
||||||
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1197,6 +1197,11 @@ INSERT INTO `vn`.`train`(`id`, `name`)
|
||||||
(1, 'Train1'),
|
(1, 'Train1'),
|
||||||
(2, 'Train2');
|
(2, 'Train2');
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
|
||||||
|
VALUES
|
||||||
|
('1106', '1', '1', 'H', '1', '1', '1'),
|
||||||
|
('1107', '1', '1', 'V', '1', '1', '1');
|
||||||
|
|
||||||
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
|
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1106, 5, DATE_ADD(util.VN_CURDATE(),INTERVAL +1 DAY), 1),
|
(1, 1106, 5, DATE_ADD(util.VN_CURDATE(),INTERVAL +1 DAY), 1),
|
||||||
|
@ -1404,16 +1409,16 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
|
||||||
(7, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 4, 1, 50.00, 500, 'seventh travel', 2, 1),
|
(7, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 4, 1, 50.00, 500, 'seventh travel', 2, 1),
|
||||||
(8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2);
|
(8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2);
|
||||||
|
|
||||||
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `isRaid`, `notes`, `evaNotes`)
|
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `isRaid`, `evaNotes`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, 0, '', ''),
|
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, 0, ''),
|
||||||
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 0, 'this is the note two', 'observation two'),
|
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 0, 'observation two'),
|
||||||
(3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 0, 'this is the note three', 'observation three'),
|
(3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 0, 'observation three'),
|
||||||
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 0, 'this is the note four', 'observation four'),
|
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 0, 'observation four'),
|
||||||
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 0, 'this is the note five', 'observation five'),
|
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 0, 'observation five'),
|
||||||
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 0, 'this is the note six', 'observation six'),
|
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 0, 'observation six'),
|
||||||
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 0, 'this is the note seven', 'observation seven'),
|
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 0, 'observation seven'),
|
||||||
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, 1, '', '');
|
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, 1, '');
|
||||||
|
|
||||||
INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `itemFk`, `itemTypeFk`, `saleTotal`, `saleWaste`, `rate`)
|
INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `itemFk`, `itemTypeFk`, `saleTotal`, `saleWaste`, `rate`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1771,12 +1776,12 @@ INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`,
|
||||||
( 6, 'mana', 'Mana', 72, 4, 0),
|
( 6, 'mana', 'Mana', 72, 4, 0),
|
||||||
( 7, 'lack', 'Faltas', 72, 2, 0);
|
( 7, 'lack', 'Faltas', 72, 2, 0);
|
||||||
|
|
||||||
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`, `rma`)
|
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`, `rma`, `ticketFk`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, util.VN_CURDATE(), 1, 1101, 18, 3, 0, util.VN_CURDATE(), 0, '02676A049183'),
|
(1, util.VN_CURDATE(), 1, 1101, 18, 3, 0, util.VN_CURDATE(), 0, '02676A049183', 11),
|
||||||
(2, util.VN_CURDATE(), 2, 1101, 18, 3, 0, util.VN_CURDATE(), 1, NULL),
|
(2, util.VN_CURDATE(), 2, 1101, 18, 3, 0, util.VN_CURDATE(), 1, NULL, 16),
|
||||||
(3, util.VN_CURDATE(), 3, 1101, 18, 1, 1, util.VN_CURDATE(), 5, NULL),
|
(3, util.VN_CURDATE(), 3, 1101, 18, 1, 1, util.VN_CURDATE(), 5, NULL, 7),
|
||||||
(4, util.VN_CURDATE(), 3, 1104, 18, 5, 0, util.VN_CURDATE(), 10, NULL);
|
(4, util.VN_CURDATE(), 3, 1104, 18, 5, 0, util.VN_CURDATE(), 10, NULL, 8);
|
||||||
|
|
||||||
INSERT INTO `vn`.`claimObservation` (`claimFk`, `workerFk`, `text`, `created`)
|
INSERT INTO `vn`.`claimObservation` (`claimFk`, `workerFk`, `text`, `created`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2487,9 +2492,9 @@ REPLACE INTO `vn`.`invoiceIn`(`id`, `serialNumber`,`serial`, `supplierFk`, `issu
|
||||||
(9, 1009, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1242, 1, 442, 1),
|
(9, 1009, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1242, 1, 442, 1),
|
||||||
(10, 1010, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1243, 1, 442, 1);
|
(10, 1010, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1243, 1, 442, 1);
|
||||||
|
|
||||||
INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`)
|
INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`, `daysAgo`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, -2, '2% retention', 2);
|
(1, -2, '2% retention', 2, 45);
|
||||||
|
|
||||||
INSERT INTO `vn`.`invoiceInDueDay`(`invoiceInFk`, `dueDated`, `bankFk`, `amount`)
|
INSERT INTO `vn`.`invoiceInDueDay`(`invoiceInFk`, `dueDated`, `bankFk`, `amount`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2631,8 +2636,8 @@ INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackage
|
||||||
|
|
||||||
INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`)
|
INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`)
|
||||||
VALUES
|
VALUES
|
||||||
(1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 0),
|
(1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 'sent'),
|
||||||
(1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 0);
|
(1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 'pending');
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`)
|
INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`)
|
||||||
|
@ -2785,7 +2790,7 @@ INSERT INTO `vn`.`profileType` (`id`, `name`)
|
||||||
|
|
||||||
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
|
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
|
||||||
VALUES
|
VALUES
|
||||||
('lilium', 'dev', 'http://localhost:8080/#/'),
|
('lilium', 'dev', 'http://localhost:9000/#/'),
|
||||||
('salix', 'dev', 'http://localhost:5000/#!/');
|
('salix', 'dev', 'http://localhost:5000/#!/');
|
||||||
|
|
||||||
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)
|
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)
|
||||||
|
@ -2837,4 +2842,27 @@ INSERT INTO `vn`.`workerTimeControlMail` (`id`, `workerFk`, `year`, `week`, `sta
|
||||||
(3, 9, 2000, 51, 'CONFIRMED', util.VN_NOW(), 1, NULL),
|
(3, 9, 2000, 51, 'CONFIRMED', util.VN_NOW(), 1, NULL),
|
||||||
(4, 9, 2001, 1, 'SENDED', util.VN_NOW(), 1, NULL);
|
(4, 9, 2001, 1, 'SENDED', util.VN_NOW(), 1, NULL);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `maxWagonHeight`, `minHeightBetweenTrays`, `maxTrays`)
|
||||||
|
VALUES
|
||||||
|
(1, 1350, 1900, 200, 50, 6);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`)
|
||||||
|
VALUES
|
||||||
|
(1, 'white', '#ffffff'),
|
||||||
|
(2, 'red', '#ff0000'),
|
||||||
|
(3, 'green', '#00ff00'),
|
||||||
|
(4, 'blue', '#0000ff');
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`wagonType` (`id`, `name`, `divisible`)
|
||||||
|
VALUES
|
||||||
|
(1, 'Wagon Type #1', 1);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`)
|
||||||
|
VALUES
|
||||||
|
(1, 1, 100, 1),
|
||||||
|
(2, 1, 50, 2),
|
||||||
|
(3, 1, 0, 3);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42776,7 +42776,7 @@ CREATE DEFINER=`root`@`localhost` FUNCTION `hasAnyNegativeBase`() RETURNS tinyin
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
/* Calcula si existe alguna base imponible negativa
|
/* Calcula si existe alguna base imponible negativa
|
||||||
* Requiere la tabla temporal vn.ticketToInvoice(id)
|
* Requiere la tabla temporal tmp.ticketToInvoice(id)
|
||||||
*
|
*
|
||||||
* returns BOOLEAN
|
* returns BOOLEAN
|
||||||
*/
|
*/
|
||||||
|
@ -42787,7 +42787,7 @@ BEGIN
|
||||||
(KEY (ticketFk))
|
(KEY (ticketFk))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id ticketFk
|
SELECT id ticketFk
|
||||||
FROM ticketToInvoice;
|
FROM tmp.ticketToInvoice;
|
||||||
|
|
||||||
CALL ticket_getTax(NULL);
|
CALL ticket_getTax(NULL);
|
||||||
|
|
||||||
|
@ -55223,7 +55223,7 @@ DELIMITER ;;
|
||||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `invoiceExpenceMake`(IN vInvoice INT)
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `invoiceExpenceMake`(IN vInvoice INT)
|
||||||
BEGIN
|
BEGIN
|
||||||
/* Inserta las partidas de gasto correspondientes a la factura
|
/* Inserta las partidas de gasto correspondientes a la factura
|
||||||
* REQUIERE tabla ticketToInvoice
|
* REQUIERE tabla tmp.ticketToInvoice
|
||||||
* @param vInvoice Numero de factura
|
* @param vInvoice Numero de factura
|
||||||
*/
|
*/
|
||||||
DELETE FROM invoiceOutExpence
|
DELETE FROM invoiceOutExpence
|
||||||
|
@ -55233,7 +55233,7 @@ BEGIN
|
||||||
SELECT vInvoice,
|
SELECT vInvoice,
|
||||||
expenceFk,
|
expenceFk,
|
||||||
SUM(ROUND(quantity * price * (100 - discount)/100,2)) amount
|
SUM(ROUND(quantity * price * (100 - discount)/100,2)) amount
|
||||||
FROM ticketToInvoice t
|
FROM tmp.ticketToInvoice t
|
||||||
JOIN sale s ON s.ticketFk = t.id
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
JOIN item i ON i.id = s.itemFk
|
JOIN item i ON i.id = s.itemFk
|
||||||
GROUP BY i.expenceFk
|
GROUP BY i.expenceFk
|
||||||
|
@ -55243,7 +55243,7 @@ BEGIN
|
||||||
SELECT vInvoice,
|
SELECT vInvoice,
|
||||||
tst.expenceFk,
|
tst.expenceFk,
|
||||||
SUM(ROUND(ts.quantity * ts.price ,2)) amount
|
SUM(ROUND(ts.quantity * ts.price ,2)) amount
|
||||||
FROM ticketToInvoice t
|
FROM tmp.ticketToInvoice t
|
||||||
JOIN ticketService ts ON ts.ticketFk = t.id
|
JOIN ticketService ts ON ts.ticketFk = t.id
|
||||||
JOIN ticketServiceType tst ON tst.id = ts.ticketServiceTypeFk
|
JOIN ticketServiceType tst ON tst.id = ts.ticketServiceTypeFk
|
||||||
HAVING amount != 0;
|
HAVING amount != 0;
|
||||||
|
@ -55270,9 +55270,9 @@ BEGIN
|
||||||
|
|
||||||
SET vMaxTicketDate = vn2008.DAYEND(vMaxTicketDate);
|
SET vMaxTicketDate = vn2008.DAYEND(vMaxTicketDate);
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS `ticketToInvoice`;
|
DROP TEMPORARY TABLE IF EXISTS `tmp`.`ticketToInvoice`;
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE `ticketToInvoice`
|
CREATE TEMPORARY TABLE `tmp`.`ticketToInvoice`
|
||||||
(PRIMARY KEY (`id`))
|
(PRIMARY KEY (`id`))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT Id_Ticket id FROM vn2008.Tickets WHERE (Fecha BETWEEN vMinDateTicket
|
SELECT Id_Ticket id FROM vn2008.Tickets WHERE (Fecha BETWEEN vMinDateTicket
|
||||||
|
@ -55305,8 +55305,8 @@ BEGIN
|
||||||
SET vMinTicketDate = util.firstDayOfYear(vMaxTicketDate - INTERVAL 1 YEAR);
|
SET vMinTicketDate = util.firstDayOfYear(vMaxTicketDate - INTERVAL 1 YEAR);
|
||||||
SET vMaxTicketDate = util.dayend(vMaxTicketDate);
|
SET vMaxTicketDate = util.dayend(vMaxTicketDate);
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS `ticketToInvoice`;
|
DROP TEMPORARY TABLE IF EXISTS `tmp`.`ticketToInvoice`;
|
||||||
CREATE TEMPORARY TABLE `ticketToInvoice`
|
CREATE TEMPORARY TABLE `tmp`.`ticketToInvoice`
|
||||||
(PRIMARY KEY (`id`))
|
(PRIMARY KEY (`id`))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id FROM ticket t
|
SELECT id FROM ticket t
|
||||||
|
@ -55333,9 +55333,9 @@ DELIMITER ;;
|
||||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `invoiceFromTicket`(IN vTicket INT)
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `invoiceFromTicket`(IN vTicket INT)
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS `ticketToInvoice`;
|
DROP TEMPORARY TABLE IF EXISTS `tmp`.`ticketToInvoice`;
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE `ticketToInvoice`
|
CREATE TEMPORARY TABLE `tmp`.`ticketToInvoice`
|
||||||
(PRIMARY KEY (`id`))
|
(PRIMARY KEY (`id`))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id FROM vn.ticket
|
SELECT id FROM vn.ticket
|
||||||
|
@ -55931,9 +55931,9 @@ BEGIN
|
||||||
JOIN invoiceOut io ON io.companyFk = s.id
|
JOIN invoiceOut io ON io.companyFk = s.id
|
||||||
WHERE io.id = vInvoiceFk;
|
WHERE io.id = vInvoiceFk;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS ticketToInvoice;
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketToInvoice;
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE ticketToInvoice
|
CREATE TEMPORARY TABLE tmp.ticketToInvoice
|
||||||
SELECT id
|
SELECT id
|
||||||
FROM ticket
|
FROM ticket
|
||||||
WHERE refFk = vInvoiceRef;
|
WHERE refFk = vInvoiceRef;
|
||||||
|
@ -56408,9 +56408,9 @@ BEGIN
|
||||||
JOIN client c ON c.id = io.clientFk
|
JOIN client c ON c.id = io.clientFk
|
||||||
WHERE io.id = vInvoice;
|
WHERE io.id = vInvoice;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS ticketToInvoice;
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketToInvoice;
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE ticketToInvoice
|
CREATE TEMPORARY TABLE tmp.ticketToInvoice
|
||||||
SELECT id
|
SELECT id
|
||||||
FROM ticket
|
FROM ticket
|
||||||
WHERE refFk = vInvoiceRef;
|
WHERE refFk = vInvoiceRef;
|
||||||
|
@ -56456,7 +56456,7 @@ CREATE DEFINER=`root`@`localhost` PROCEDURE `invoiceOut_exportationFromClient`(
|
||||||
vCompanyFk INT)
|
vCompanyFk INT)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Genera tabla temporal ticketToInvoice necesaría para el proceso de facturación
|
* Genera tabla temporal tmp.ticketToInvoice necesaría para el proceso de facturación
|
||||||
* Los abonos quedan excluidos en las exportaciones
|
* Los abonos quedan excluidos en las exportaciones
|
||||||
*
|
*
|
||||||
* @param vMaxTicketDate Fecha hasta la cual cogerá tickets para facturar
|
* @param vMaxTicketDate Fecha hasta la cual cogerá tickets para facturar
|
||||||
|
@ -56467,8 +56467,8 @@ BEGIN
|
||||||
SET vMinTicketDate = util.firstDayOfYear(vMaxTicketDate - INTERVAL 1 YEAR);
|
SET vMinTicketDate = util.firstDayOfYear(vMaxTicketDate - INTERVAL 1 YEAR);
|
||||||
SET vMaxTicketDate = util.dayend(vMaxTicketDate);
|
SET vMaxTicketDate = util.dayend(vMaxTicketDate);
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS `ticketToInvoice`;
|
DROP TEMPORARY TABLE IF EXISTS `tmp`.`ticketToInvoice`;
|
||||||
CREATE TEMPORARY TABLE `ticketToInvoice`
|
CREATE TEMPORARY TABLE `tmp`.`ticketToInvoice`
|
||||||
(PRIMARY KEY (`id`))
|
(PRIMARY KEY (`id`))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT t.id
|
SELECT t.id
|
||||||
|
@ -56503,7 +56503,7 @@ CREATE DEFINER=`root`@`localhost` PROCEDURE `invoiceOut_new`(
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Creación de facturas emitidas.
|
* Creación de facturas emitidas.
|
||||||
* requiere previamente tabla ticketToInvoice(id).
|
* requiere previamente tabla tmp.ticketToInvoice(id).
|
||||||
*
|
*
|
||||||
* @param vSerial serie a la cual se hace la factura
|
* @param vSerial serie a la cual se hace la factura
|
||||||
* @param vInvoiceDate fecha de la factura
|
* @param vInvoiceDate fecha de la factura
|
||||||
|
@ -56531,13 +56531,13 @@ BEGIN
|
||||||
|
|
||||||
SELECT t.clientFk, t.companyFk
|
SELECT t.clientFk, t.companyFk
|
||||||
INTO vClientFk, vCompanyFk
|
INTO vClientFk, vCompanyFk
|
||||||
FROM ticketToInvoice tt
|
FROM tmp.ticketToInvoice tt
|
||||||
JOIN ticket t ON t.id = tt.id
|
JOIN ticket t ON t.id = tt.id
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
-- Eliminem de ticketToInvoice els tickets que no han de ser facturats
|
-- Eliminem de tmp.ticketToInvoice els tickets que no han de ser facturats
|
||||||
DELETE ti.*
|
DELETE ti.*
|
||||||
FROM ticketToInvoice ti
|
FROM tmp.ticketToInvoice ti
|
||||||
JOIN ticket t ON t.id = ti.id
|
JOIN ticket t ON t.id = ti.id
|
||||||
JOIN sale s ON s.ticketFk = t.id
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
JOIN item i ON i.id = s.itemFk
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
@ -56552,7 +56552,7 @@ BEGIN
|
||||||
|
|
||||||
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100), ts.id
|
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100), ts.id
|
||||||
INTO vIsAnySaleToInvoice, vIsAnyServiceToInvoice
|
INTO vIsAnySaleToInvoice, vIsAnyServiceToInvoice
|
||||||
FROM ticketToInvoice t
|
FROM tmp.ticketToInvoice t
|
||||||
LEFT JOIN sale s ON s.ticketFk = t.id
|
LEFT JOIN sale s ON s.ticketFk = t.id
|
||||||
LEFT JOIN ticketService ts ON ts.ticketFk = t.id;
|
LEFT JOIN ticketService ts ON ts.ticketFk = t.id;
|
||||||
|
|
||||||
|
@ -56593,13 +56593,13 @@ BEGIN
|
||||||
WHERE id = vNewInvoiceId;
|
WHERE id = vNewInvoiceId;
|
||||||
|
|
||||||
UPDATE ticket t
|
UPDATE ticket t
|
||||||
JOIN ticketToInvoice ti ON ti.id = t.id
|
JOIN tmp.ticketToInvoice ti ON ti.id = t.id
|
||||||
SET t.refFk = vNewRef;
|
SET t.refFk = vNewRef;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
|
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
|
||||||
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
|
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
|
||||||
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
|
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
|
||||||
FROM ticketToInvoice ti
|
FROM tmp.ticketToInvoice ti
|
||||||
LEFT JOIN ticketState ts ON ti.id = ts.ticket
|
LEFT JOIN ticketState ts ON ti.id = ts.ticket
|
||||||
JOIN state s
|
JOIN state s
|
||||||
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
|
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
|
||||||
|
@ -56609,7 +56609,7 @@ BEGIN
|
||||||
|
|
||||||
INSERT INTO ticketLog (action, userFk, originFk, description)
|
INSERT INTO ticketLog (action, userFk, originFk, description)
|
||||||
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
||||||
FROM ticketToInvoice ti;
|
FROM tmp.ticketToInvoice ti;
|
||||||
|
|
||||||
CALL invoiceExpenceMake(vNewInvoiceId);
|
CALL invoiceExpenceMake(vNewInvoiceId);
|
||||||
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
||||||
|
@ -56647,7 +56647,7 @@ BEGIN
|
||||||
(KEY (ticketFk))
|
(KEY (ticketFk))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id ticketFk
|
SELECT id ticketFk
|
||||||
FROM ticketToInvoice;
|
FROM tmp.ticketToInvoice;
|
||||||
|
|
||||||
CALL `ticket_getTax`('NATIONAL');
|
CALL `ticket_getTax`('NATIONAL');
|
||||||
|
|
||||||
|
@ -56725,7 +56725,7 @@ BEGIN
|
||||||
DROP TEMPORARY TABLE tmp.ticketServiceTax;
|
DROP TEMPORARY TABLE tmp.ticketServiceTax;
|
||||||
END IF;
|
END IF;
|
||||||
END IF;
|
END IF;
|
||||||
DROP TEMPORARY TABLE `ticketToInvoice`;
|
DROP TEMPORARY TABLE `tmp`.`ticketToInvoice`;
|
||||||
END ;;
|
END ;;
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||||
|
@ -56876,7 +56876,7 @@ BEGIN
|
||||||
(KEY (ticketFk))
|
(KEY (ticketFk))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id ticketFk
|
SELECT id ticketFk
|
||||||
FROM ticketToInvoice;
|
FROM tmp.ticketToInvoice;
|
||||||
|
|
||||||
CALL ticket_getTax(vTaxArea);
|
CALL ticket_getTax(vTaxArea);
|
||||||
|
|
||||||
|
@ -68689,7 +68689,7 @@ DELIMITER ;
|
||||||
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
/*!50003 DROP PROCEDURE IF EXISTS `ticketToInvoiceByAddress` */;
|
/*!50003 DROP PROCEDURE IF EXISTS `tmp`.`ticketToInvoiceByAddress` */;
|
||||||
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||||
|
@ -68709,9 +68709,9 @@ BEGIN
|
||||||
|
|
||||||
SET vEnded = util.dayEnd(vEnded);
|
SET vEnded = util.dayEnd(vEnded);
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS vn.ticketToInvoice;
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketToInvoice;
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE vn.ticketToInvoice
|
CREATE TEMPORARY TABLE tmp.ticketToInvoice
|
||||||
SELECT id
|
SELECT id
|
||||||
FROM vn.ticket
|
FROM vn.ticket
|
||||||
WHERE addressFk = vAddress
|
WHERE addressFk = vAddress
|
||||||
|
@ -68745,9 +68745,9 @@ BEGIN
|
||||||
|
|
||||||
SET vEnded = util.dayEnd(vEnded);
|
SET vEnded = util.dayEnd(vEnded);
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS vn.ticketToInvoice;
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketToInvoice;
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE vn.ticketToInvoice
|
CREATE TEMPORARY TABLE tmp.ticketToInvoice
|
||||||
SELECT id
|
SELECT id
|
||||||
FROM vn.ticket
|
FROM vn.ticket
|
||||||
WHERE clientFk = vClient
|
WHERE clientFk = vClient
|
||||||
|
@ -68808,9 +68808,9 @@ BEGIN
|
||||||
JOIN vn.client c ON c.id = io.clientFk
|
JOIN vn.client c ON c.id = io.clientFk
|
||||||
WHERE io.id = vInvoice;
|
WHERE io.id = vInvoice;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS vn.ticketToInvoice;
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketToInvoice;
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE vn.ticketToInvoice
|
CREATE TEMPORARY TABLE tmp.ticketToInvoice
|
||||||
SELECT id
|
SELECT id
|
||||||
FROM vn.ticket
|
FROM vn.ticket
|
||||||
WHERE refFk = vInvoiceRef;
|
WHERE refFk = vInvoiceRef;
|
||||||
|
|
|
@ -68,6 +68,7 @@ TABLES=(
|
||||||
time
|
time
|
||||||
volumeConfig
|
volumeConfig
|
||||||
workCenter
|
workCenter
|
||||||
|
companyI18n
|
||||||
)
|
)
|
||||||
dump_tables ${TABLES[@]}
|
dump_tables ${TABLES[@]}
|
||||||
|
|
||||||
|
|
|
@ -156,14 +156,14 @@ let actions = {
|
||||||
await this.waitForSpinnerLoad();
|
await this.waitForSpinnerLoad();
|
||||||
},
|
},
|
||||||
|
|
||||||
accessToSection: async function(state) {
|
accessToSection: async function(state, name = 'Others') {
|
||||||
await this.waitForSelector('vn-left-menu');
|
await this.waitForSelector('vn-left-menu');
|
||||||
let nested = await this.evaluate(state => {
|
let nested = await this.evaluate(state => {
|
||||||
return document.querySelector(`vn-left-menu li li > a[ui-sref="${state}"]`) != null;
|
return document.querySelector(`vn-left-menu li li > a[ui-sref="${state}"]`) != null;
|
||||||
}, state);
|
}, state);
|
||||||
|
|
||||||
if (nested) {
|
if (nested) {
|
||||||
let selector = 'vn-left-menu vn-item-section > vn-icon[icon=keyboard_arrow_down]';
|
let selector = `vn-left-menu li[name="${name}"]`;
|
||||||
await this.evaluate(selector => {
|
await this.evaluate(selector => {
|
||||||
document.querySelector(selector).scrollIntoViewIfNeeded();
|
document.querySelector(selector).scrollIntoViewIfNeeded();
|
||||||
}, selector);
|
}, selector);
|
||||||
|
@ -414,7 +414,7 @@ let actions = {
|
||||||
const selector = 'vn-snackbar .shape.shown';
|
const selector = 'vn-snackbar .shape.shown';
|
||||||
await this.waitForSelector(selector);
|
await this.waitForSelector(selector);
|
||||||
|
|
||||||
let message = await this.evaluate(selector => {
|
const message = await this.evaluate(selector => {
|
||||||
const shape = document.querySelector(selector);
|
const shape = document.querySelector(selector);
|
||||||
const message = {
|
const message = {
|
||||||
text: shape.querySelector('.text').innerText
|
text: shape.querySelector('.text').innerText
|
||||||
|
@ -431,6 +431,8 @@ let actions = {
|
||||||
return message;
|
return message;
|
||||||
}, selector);
|
}, selector);
|
||||||
|
|
||||||
|
message.isSuccess = message.type == 'success';
|
||||||
|
|
||||||
await this.hideSnackbar();
|
await this.hideSnackbar();
|
||||||
return message;
|
return message;
|
||||||
},
|
},
|
||||||
|
@ -466,28 +468,6 @@ let actions = {
|
||||||
}, selector);
|
}, selector);
|
||||||
},
|
},
|
||||||
|
|
||||||
clearInput: async function(selector) {
|
|
||||||
await this.waitForSelector(selector);
|
|
||||||
|
|
||||||
let field = await this.evaluate(selector => {
|
|
||||||
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field;
|
|
||||||
}, selector);
|
|
||||||
|
|
||||||
if ((field != null && field != '') || field == '0') {
|
|
||||||
let coords = await this.evaluate(selector => {
|
|
||||||
let rect = document.querySelector(selector).getBoundingClientRect();
|
|
||||||
return {x: rect.x + (rect.width / 2), y: rect.y + (rect.height / 2), width: rect.width};
|
|
||||||
}, selector);
|
|
||||||
await this.mouse.move(coords.x, coords.y);
|
|
||||||
await this.waitForSelector(`${selector} [icon="clear"]`, {visible: true});
|
|
||||||
await this.waitToClick(`${selector} [icon="clear"]`);
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.evaluate(selector => {
|
|
||||||
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field == '';
|
|
||||||
}, selector);
|
|
||||||
},
|
|
||||||
|
|
||||||
autocompleteSearch: async function(selector, searchValue) {
|
autocompleteSearch: async function(selector, searchValue) {
|
||||||
let builtSelector = await this.selectorFormater(selector);
|
let builtSelector = await this.selectorFormater(selector);
|
||||||
|
|
||||||
|
@ -519,17 +499,15 @@ let actions = {
|
||||||
|
|
||||||
checkboxState: async function(selector) {
|
checkboxState: async function(selector) {
|
||||||
await this.waitForSelector(selector);
|
await this.waitForSelector(selector);
|
||||||
return this.evaluate(selector => {
|
const value = await this.getInputValue(selector);
|
||||||
let checkbox = document.querySelector(selector);
|
switch (value) {
|
||||||
switch (checkbox.$ctrl.field) {
|
case null:
|
||||||
case null:
|
return 'intermediate';
|
||||||
return 'intermediate';
|
case true:
|
||||||
case true:
|
return 'checked';
|
||||||
return 'checked';
|
default:
|
||||||
default:
|
return 'unchecked';
|
||||||
return 'unchecked';
|
}
|
||||||
}
|
|
||||||
}, selector);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isDisabled: async function(selector) {
|
isDisabled: async function(selector) {
|
||||||
|
@ -622,6 +600,138 @@ let actions = {
|
||||||
|
|
||||||
waitForContentLoaded: async function() {
|
waitForContentLoaded: async function() {
|
||||||
await this.waitForSpinnerLoad();
|
await this.waitForSpinnerLoad();
|
||||||
|
},
|
||||||
|
|
||||||
|
async getInputValue(selector) {
|
||||||
|
return this.evaluate(selector => {
|
||||||
|
const input = document.querySelector(selector);
|
||||||
|
return input.$ctrl.field;
|
||||||
|
}, selector);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getValue(selector) {
|
||||||
|
return await this.waitToGetProperty(selector, 'value');
|
||||||
|
},
|
||||||
|
|
||||||
|
async innerText(selector) {
|
||||||
|
const element = await this.$(selector);
|
||||||
|
const handle = await element.getProperty('innerText');
|
||||||
|
return handle.jsonValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
async setInput(selector, value) {
|
||||||
|
const input = await this.$(selector);
|
||||||
|
const tagName = (await input.evaluate(e => e.tagName)).toLowerCase();
|
||||||
|
|
||||||
|
switch (tagName) {
|
||||||
|
case 'vn-textfield':
|
||||||
|
case 'vn-datalist':
|
||||||
|
case 'vn-input-number':
|
||||||
|
await this.clearInput(selector);
|
||||||
|
if (value)
|
||||||
|
await this.write(selector, value.toString());
|
||||||
|
break;
|
||||||
|
case 'vn-autocomplete':
|
||||||
|
if (value)
|
||||||
|
await this.autocompleteSearch(selector, value.toString());
|
||||||
|
else
|
||||||
|
await this.clearInput(selector);
|
||||||
|
break;
|
||||||
|
case 'vn-date-picker':
|
||||||
|
if (value)
|
||||||
|
await this.pickDate(selector, value);
|
||||||
|
else
|
||||||
|
await this.clearInput(selector);
|
||||||
|
break;
|
||||||
|
case 'vn-input-time':
|
||||||
|
if (value)
|
||||||
|
await this.pickTime(selector, value);
|
||||||
|
else
|
||||||
|
await this.clearInput(selector);
|
||||||
|
break;
|
||||||
|
case 'vn-check':
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
if (await this.getInput(selector) == value) break;
|
||||||
|
await this.click(selector);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getInput(selector) {
|
||||||
|
const input = await this.$(selector);
|
||||||
|
const tagName = (await input.evaluate(e => e.tagName)).toLowerCase();
|
||||||
|
let el;
|
||||||
|
let value;
|
||||||
|
|
||||||
|
switch (tagName) {
|
||||||
|
case 'vn-textfield':
|
||||||
|
case 'vn-autocomplete':
|
||||||
|
case 'vn-input-time':
|
||||||
|
case 'vn-datalist':
|
||||||
|
el = await input.$('input');
|
||||||
|
value = await el.getProperty('value');
|
||||||
|
return value.jsonValue();
|
||||||
|
case 'vn-check':
|
||||||
|
case 'vn-input-number':
|
||||||
|
return await this.getInputValue(selector);
|
||||||
|
case 'vn-textarea':
|
||||||
|
el = await input.$('textarea');
|
||||||
|
value = await el.getProperty('value');
|
||||||
|
return value.jsonValue();
|
||||||
|
case 'vn-date-picker':
|
||||||
|
el = await input.$('input');
|
||||||
|
value = await el.getProperty('value');
|
||||||
|
if (value) {
|
||||||
|
const date = new Date(await value.jsonValue());
|
||||||
|
date.setUTCHours(0, 0, 0, 0);
|
||||||
|
return date;
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
value = await this.innerText(selector);
|
||||||
|
return value.jsonValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async clearInput(selector) {
|
||||||
|
await this.waitForSelector(selector);
|
||||||
|
|
||||||
|
let field = await this.evaluate(selector => {
|
||||||
|
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field;
|
||||||
|
}, selector);
|
||||||
|
|
||||||
|
if ((field != null && field != '') || field == '0') {
|
||||||
|
let coords = await this.evaluate(selector => {
|
||||||
|
let rect = document.querySelector(selector).getBoundingClientRect();
|
||||||
|
return {x: rect.x + (rect.width / 2), y: rect.y + (rect.height / 2), width: rect.width};
|
||||||
|
}, selector);
|
||||||
|
await this.mouse.move(coords.x, coords.y);
|
||||||
|
await this.waitForSelector(`${selector} [icon="clear"]`, {visible: true});
|
||||||
|
await this.waitToClick(`${selector} [icon="clear"]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.evaluate(selector => {
|
||||||
|
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field == '';
|
||||||
|
}, selector);
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchForm(selector, inputNames) {
|
||||||
|
const values = {};
|
||||||
|
for (const inputName of inputNames)
|
||||||
|
values[inputName] = await this.getInput(`${selector} [vn-name="${inputName}"]`);
|
||||||
|
return values;
|
||||||
|
},
|
||||||
|
|
||||||
|
async fillForm(selector, values) {
|
||||||
|
for (const inputName in values)
|
||||||
|
await this.setInput(`${selector} [vn-name="${inputName}"]`, values[inputName]);
|
||||||
|
},
|
||||||
|
|
||||||
|
async sendForm(selector, values) {
|
||||||
|
if (values) await this.fillForm(selector, values);
|
||||||
|
await this.click(`${selector} button[type=submit]`);
|
||||||
|
return await this.waitForSnackbar();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -629,12 +739,14 @@ export function extendPage(page) {
|
||||||
for (let name in actions) {
|
for (let name in actions) {
|
||||||
page[name] = async(...args) => {
|
page[name] = async(...args) => {
|
||||||
try {
|
try {
|
||||||
return actions[name].apply(page, args);
|
return await actions[name].apply(page, args);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
let stringArgs = args
|
let stringArgs = args
|
||||||
.map(i => typeof i == 'function' ? 'Function' : i)
|
.map(i => typeof i == 'function' ? 'Function' : `'${i}'`)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
throw new Error(`.${name}(${stringArgs}): ${err.message}`);
|
const myErr = new Error(`${err.message}\n at Page.${name}(${stringArgs})`);
|
||||||
|
myErr.stack = err.stack;
|
||||||
|
throw myErr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,10 +193,6 @@ export default {
|
||||||
saveNewPoscode: '#savePostcode',
|
saveNewPoscode: '#savePostcode',
|
||||||
createButton: 'vn-client-create button[type=submit]'
|
createButton: 'vn-client-create button[type=submit]'
|
||||||
},
|
},
|
||||||
clientDescriptor: {
|
|
||||||
moreMenu: 'vn-client-descriptor vn-icon-button[icon=more_vert]',
|
|
||||||
simpleTicketButton: '.vn-menu [name="simpleTicket"]'
|
|
||||||
},
|
|
||||||
clientBasicData: {
|
clientBasicData: {
|
||||||
name: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.name"]',
|
name: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.name"]',
|
||||||
contact: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.contact"]',
|
contact: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.contact"]',
|
||||||
|
@ -231,23 +227,6 @@ export default {
|
||||||
saveButton: 'button[type=submit]',
|
saveButton: 'button[type=submit]',
|
||||||
watcher: 'vn-client-fiscal-data vn-watcher'
|
watcher: 'vn-client-fiscal-data vn-watcher'
|
||||||
},
|
},
|
||||||
clientBillingData: {
|
|
||||||
payMethod: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]',
|
|
||||||
IBAN: 'vn-client-billing-data vn-textfield[ng-model="$ctrl.client.iban"]',
|
|
||||||
dueDay: 'vn-client-billing-data vn-input-number[ng-model="$ctrl.client.dueDay"]',
|
|
||||||
receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]',
|
|
||||||
receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]',
|
|
||||||
receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]',
|
|
||||||
swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]',
|
|
||||||
newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button',
|
|
||||||
newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.name"]',
|
|
||||||
newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.bic"]',
|
|
||||||
newBankEntityCountry: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.data.countryFk"]',
|
|
||||||
newBankEntityCode: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.id"]',
|
|
||||||
acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]',
|
|
||||||
saveButton: 'vn-client-billing-data button[type=submit]',
|
|
||||||
watcher: 'vn-client-billing-data vn-watcher'
|
|
||||||
},
|
|
||||||
clientAddresses: {
|
clientAddresses: {
|
||||||
addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]',
|
addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]',
|
||||||
createAddress: 'vn-client-address-index vn-float-button',
|
createAddress: 'vn-client-address-index vn-float-button',
|
||||||
|
@ -283,12 +262,6 @@ export default {
|
||||||
cancelEditAddressButton: 'vn-client-address-edit > form > vn-button-bar > vn-button > button',
|
cancelEditAddressButton: 'vn-client-address-edit > form > vn-button-bar > vn-button > button',
|
||||||
watcher: 'vn-client-address-edit vn-watcher'
|
watcher: 'vn-client-address-edit vn-watcher'
|
||||||
},
|
},
|
||||||
clientWebAccess: {
|
|
||||||
enableWebAccessCheckbox: 'vn-check[label="Enable web access"]',
|
|
||||||
userName: 'vn-client-web-access vn-textfield[ng-model="$ctrl.account.name"]',
|
|
||||||
email: 'vn-client-web-access vn-textfield[ng-model="$ctrl.account.email"]',
|
|
||||||
saveButton: 'button[type=submit]'
|
|
||||||
},
|
|
||||||
clientNotes: {
|
clientNotes: {
|
||||||
addNoteFloatButton: 'vn-float-button',
|
addNoteFloatButton: 'vn-float-button',
|
||||||
note: 'vn-textarea[ng-model="$ctrl.note.text"]',
|
note: 'vn-textarea[ng-model="$ctrl.note.text"]',
|
||||||
|
@ -312,30 +285,6 @@ export default {
|
||||||
clientMandate: {
|
clientMandate: {
|
||||||
firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr'
|
firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr'
|
||||||
},
|
},
|
||||||
clientLog: {
|
|
||||||
lastModificationPreviousValue: 'vn-client-log vn-tr table tr td.before',
|
|
||||||
lastModificationCurrentValue: 'vn-client-log vn-tr table tr td.after',
|
|
||||||
namePreviousValue: 'vn-client-log vn-tr table tr:nth-child(1) td.before',
|
|
||||||
nameCurrentValue: 'vn-client-log vn-tr table tr:nth-child(1) td.after',
|
|
||||||
activePreviousValue: 'vn-client-log vn-tr:nth-child(2) table tr:nth-child(2) td.before',
|
|
||||||
activeCurrentValue: 'vn-client-log vn-tr:nth-child(2) table tr:nth-child(2) td.after'
|
|
||||||
|
|
||||||
},
|
|
||||||
clientBalance: {
|
|
||||||
company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]',
|
|
||||||
newPaymentButton: `vn-float-button`,
|
|
||||||
newPaymentBank: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.bankFk"]',
|
|
||||||
newPaymentAmount: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.amountPaid"]',
|
|
||||||
newDescription: 'vn-textfield[ng-model="$ctrl.receipt.description"]',
|
|
||||||
deliveredAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.deliveredAmount"]',
|
|
||||||
refundAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.amountToReturn"]',
|
|
||||||
saveButton: '.vn-dialog.shown [response="accept"]',
|
|
||||||
anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr',
|
|
||||||
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
|
|
||||||
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
|
|
||||||
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield',
|
|
||||||
compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]'
|
|
||||||
},
|
|
||||||
webPayment: {
|
webPayment: {
|
||||||
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
|
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
|
||||||
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]'
|
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]'
|
||||||
|
@ -414,7 +363,7 @@ export default {
|
||||||
saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button'
|
saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button'
|
||||||
},
|
},
|
||||||
itemFixedPrice: {
|
itemFixedPrice: {
|
||||||
add: 'vn-fixed-price vn-icon-button[icon="add_circle"]',
|
add: 'vn-fixed-price vn-icon-button[vn-tooltip="Add fixed price"]',
|
||||||
firstItemID: 'vn-fixed-price tr:nth-child(2) vn-autocomplete[ng-model="price.itemFk"]',
|
firstItemID: 'vn-fixed-price tr:nth-child(2) vn-autocomplete[ng-model="price.itemFk"]',
|
||||||
fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)',
|
fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)',
|
||||||
fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]',
|
fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]',
|
||||||
|
@ -426,7 +375,19 @@ export default {
|
||||||
fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]',
|
fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]',
|
||||||
fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]',
|
fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]',
|
||||||
fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]',
|
fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]',
|
||||||
orderColumnId: 'vn-fixed-price th[field="itemFk"]'
|
orderColumnId: 'vn-fixed-price th[field="itemFk"]',
|
||||||
|
removeWarehouseFilter: 'vn-searchbar > form > vn-textfield > div.container > div.prepend > prepend > div > span:nth-child(1) > vn-icon > i',
|
||||||
|
generalSearchFilter: 'vn-fixed-price-search-panel vn-textfield[ng-model="$ctrl.filter.search"]',
|
||||||
|
reignFilter: 'vn-fixed-price-search-panel vn-horizontal.item-category vn-one',
|
||||||
|
typeFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="$ctrl.filter.typeFk"]',
|
||||||
|
buyerFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="$ctrl.filter.buyerFk"]',
|
||||||
|
warehouseFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="$ctrl.filter.warehouseFk"]',
|
||||||
|
mineFilter: 'vn-fixed-price-search-panel vn-check[ng-model="$ctrl.filter.mine"]',
|
||||||
|
hasMinPriceFilter: 'vn-fixed-price-search-panel vn-check[ng-model="$ctrl.filter.hasMinPrice"]',
|
||||||
|
addTag: 'vn-fixed-price-search-panel vn-icon-button[icon="add_circle"]',
|
||||||
|
tagFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="itemTag.tagFk"]',
|
||||||
|
tagValueFilter: 'vn-fixed-price-search-panel vn-autocomplete[ng-model="itemTag.value"]',
|
||||||
|
chip: 'vn-fixed-price-search-panel vn-chip > vn-icon'
|
||||||
},
|
},
|
||||||
itemCreateView: {
|
itemCreateView: {
|
||||||
temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]',
|
temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]',
|
||||||
|
@ -469,10 +430,6 @@ export default {
|
||||||
packingOut: 'vn-input-number[ng-model="$ctrl.item.packingOut"]',
|
packingOut: 'vn-input-number[ng-model="$ctrl.item.packingOut"]',
|
||||||
isActiveCheckbox: 'vn-check[label="Active"]',
|
isActiveCheckbox: 'vn-check[label="Active"]',
|
||||||
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
|
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
|
||||||
newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button',
|
|
||||||
newIntrastatId: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.newIntrastat.intrastatId"]',
|
|
||||||
newIntrastatDescription: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newIntrastat.description"]',
|
|
||||||
acceptIntrastatButton: '.vn-dialog.shown button[response="accept"]',
|
|
||||||
submitBasicDataButton: `button[type=submit]`
|
submitBasicDataButton: `button[type=submit]`
|
||||||
},
|
},
|
||||||
itemTags: {
|
itemTags: {
|
||||||
|
@ -524,7 +481,6 @@ export default {
|
||||||
},
|
},
|
||||||
itemLog: {
|
itemLog: {
|
||||||
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
|
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
|
||||||
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(5) td.after',
|
|
||||||
},
|
},
|
||||||
ticketSummary: {
|
ticketSummary: {
|
||||||
header: 'vn-ticket-summary > vn-card > h5',
|
header: 'vn-ticket-summary > vn-card > h5',
|
||||||
|
@ -626,13 +582,6 @@ export default {
|
||||||
saveButton: '.vn-dialog.shown [response="accept"]',
|
saveButton: '.vn-dialog.shown [response="accept"]',
|
||||||
expeditionRow: 'vn-ticket-expedition vn-table vn-tbody > vn-tr'
|
expeditionRow: 'vn-ticket-expedition vn-table vn-tbody > vn-tr'
|
||||||
},
|
},
|
||||||
ticketPackages: {
|
|
||||||
firstPackage: 'vn-autocomplete[label="Package"]',
|
|
||||||
firstQuantity: 'vn-ticket-package vn-horizontal:nth-child(1) vn-input-number[ng-model="package.quantity"]',
|
|
||||||
firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]',
|
|
||||||
addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]',
|
|
||||||
savePackagesButton: `button[type=submit]`
|
|
||||||
},
|
|
||||||
ticketSales: {
|
ticketSales: {
|
||||||
setOk: 'vn-ticket-sale vn-tool-bar > vn-button[label="Ok"] > button',
|
setOk: 'vn-ticket-sale vn-tool-bar > vn-button[label="Ok"] > button',
|
||||||
saleLine: 'vn-table div > vn-tbody > vn-tr vn-check',
|
saleLine: 'vn-table div > vn-tbody > vn-tr vn-check',
|
||||||
|
@ -744,6 +693,7 @@ export default {
|
||||||
anyDocument: 'vn-ticket-dms-index > vn-data-viewer vn-tbody vn-tr'
|
anyDocument: 'vn-ticket-dms-index > vn-data-viewer vn-tbody vn-tr'
|
||||||
},
|
},
|
||||||
ticketFuture: {
|
ticketFuture: {
|
||||||
|
searchResult: 'vn-ticket-future tbody tr',
|
||||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||||
originDated: 'vn-date-picker[label="Origin date"]',
|
originDated: 'vn-date-picker[label="Origin date"]',
|
||||||
futureDated: 'vn-date-picker[label="Destination date"]',
|
futureDated: 'vn-date-picker[label="Destination date"]',
|
||||||
|
@ -759,7 +709,6 @@ export default {
|
||||||
problems: 'vn-check[label="With problems"]',
|
problems: 'vn-check[label="With problems"]',
|
||||||
tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
|
tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
|
||||||
moveButton: 'vn-button[vn-tooltip="Future tickets"]',
|
moveButton: 'vn-button[vn-tooltip="Future tickets"]',
|
||||||
acceptButton: '.vn-confirm.shown button[response="accept"]',
|
|
||||||
firstCheck: 'tbody > tr:nth-child(1) > td > vn-check',
|
firstCheck: 'tbody > tr:nth-child(1) > td > vn-check',
|
||||||
multiCheck: 'vn-multi-check',
|
multiCheck: 'vn-multi-check',
|
||||||
tableId: 'vn-textfield[name="id"]',
|
tableId: 'vn-textfield[name="id"]',
|
||||||
|
@ -877,15 +826,6 @@ export default {
|
||||||
landedDatePicker: 'vn-date-picker[label="Landed"]',
|
landedDatePicker: 'vn-date-picker[label="Landed"]',
|
||||||
createButton: 'button[type=submit]'
|
createButton: 'button[type=submit]'
|
||||||
},
|
},
|
||||||
orderSummary: {
|
|
||||||
id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span',
|
|
||||||
alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span',
|
|
||||||
consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(6) span',
|
|
||||||
subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)',
|
|
||||||
vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)',
|
|
||||||
total: 'vn-order-summary vn-one.taxes > p:nth-child(3)',
|
|
||||||
sale: 'vn-order-summary vn-tbody > vn-tr',
|
|
||||||
},
|
|
||||||
orderCatalog: {
|
orderCatalog: {
|
||||||
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
|
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
|
||||||
type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]',
|
type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]',
|
||||||
|
@ -903,14 +843,6 @@ export default {
|
||||||
fifthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(5) vn-icon[icon=cancel]',
|
fifthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(5) vn-icon[icon=cancel]',
|
||||||
sixthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(6) vn-icon[icon=cancel]',
|
sixthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(6) vn-icon[icon=cancel]',
|
||||||
},
|
},
|
||||||
orderBasicData: {
|
|
||||||
client: 'vn-autocomplete[label="Client"]',
|
|
||||||
address: 'vn-autocomplete[label="Address"]',
|
|
||||||
agency: 'vn-autocomplete[label="Agency"]',
|
|
||||||
observation: 'vn-textarea[label="Notes"]',
|
|
||||||
saveButton: `button[type=submit]`,
|
|
||||||
acceptButton: '.vn-confirm.shown button[response="accept"]'
|
|
||||||
},
|
|
||||||
orderLine: {
|
orderLine: {
|
||||||
orderSubtotal: 'vn-order-line .header :first-child',
|
orderSubtotal: 'vn-order-line .header :first-child',
|
||||||
firstLineDeleteButton: 'vn-order-line vn-tbody > vn-tr:nth-child(1) vn-icon[icon="delete"]',
|
firstLineDeleteButton: 'vn-order-line vn-tbody > vn-tr:nth-child(1) vn-icon[icon="delete"]',
|
||||||
|
@ -950,16 +882,6 @@ export default {
|
||||||
goToRouteSummaryButton: 'vn-route-summary > vn-card > h5 > a',
|
goToRouteSummaryButton: 'vn-route-summary > vn-card > h5 > a',
|
||||||
|
|
||||||
},
|
},
|
||||||
routeBasicData: {
|
|
||||||
worker: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
|
|
||||||
vehicle: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.vehicleFk"]',
|
|
||||||
kmStart: 'vn-route-basic-data vn-input-number[ng-model="$ctrl.route.kmStart"]',
|
|
||||||
kmEnd: 'vn-route-basic-data vn-input-number[ng-model="$ctrl.route.kmEnd"]',
|
|
||||||
createdDate: 'vn-route-basic-data vn-date-picker[ng-model="$ctrl.route.created"]',
|
|
||||||
startedHour: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.started"]',
|
|
||||||
finishedHour: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.finished"]',
|
|
||||||
saveButton: 'vn-route-basic-data button[type=submit]'
|
|
||||||
},
|
|
||||||
routeTickets: {
|
routeTickets: {
|
||||||
firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-input-number[ng-model="ticket.priority"]',
|
firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-input-number[ng-model="ticket.priority"]',
|
||||||
firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check',
|
firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check',
|
||||||
|
@ -988,6 +910,12 @@ export default {
|
||||||
locker: 'vn-worker-basic-data vn-input-number[ng-model="$ctrl.worker.locker"]',
|
locker: 'vn-worker-basic-data vn-input-number[ng-model="$ctrl.worker.locker"]',
|
||||||
saveButton: 'vn-worker-basic-data button[type=submit]'
|
saveButton: 'vn-worker-basic-data button[type=submit]'
|
||||||
},
|
},
|
||||||
|
workerNotes: {
|
||||||
|
addNoteFloatButton: 'vn-worker-note vn-icon[icon="add"]',
|
||||||
|
note: 'vn-note-worker-create vn-textarea[ng-model="$ctrl.note.text"]',
|
||||||
|
saveButton: 'vn-note-worker-create button[type=submit]',
|
||||||
|
firstNoteText: 'vn-worker-note .text'
|
||||||
|
},
|
||||||
workerPbx: {
|
workerPbx: {
|
||||||
extension: 'vn-worker-pbx vn-textfield[ng-model="$ctrl.worker.sip.extension"]',
|
extension: 'vn-worker-pbx vn-textfield[ng-model="$ctrl.worker.sip.extension"]',
|
||||||
saveButton: 'vn-worker-pbx button[type=submit]'
|
saveButton: 'vn-worker-pbx button[type=submit]'
|
||||||
|
@ -1128,6 +1056,15 @@ export default {
|
||||||
saveButton: 'vn-invoice-in-tax vn-submit',
|
saveButton: 'vn-invoice-in-tax vn-submit',
|
||||||
|
|
||||||
},
|
},
|
||||||
|
invoiceInIndex: {
|
||||||
|
topbarSearchParams: 'vn-searchbar div.search-params > span',
|
||||||
|
},
|
||||||
|
invoiceInSerial: {
|
||||||
|
daysAgo: 'vn-invoice-in-serial-search-panel vn-input-number[ng-model="$ctrl.filter.daysAgo"]',
|
||||||
|
serial: 'vn-invoice-in-serial-search-panel vn-textfield[ng-model="$ctrl.filter.serial"]',
|
||||||
|
chip: 'vn-chip > vn-icon',
|
||||||
|
goToIndex: 'vn-invoice-in-serial vn-icon-button[icon="icon-invoice-in"]',
|
||||||
|
},
|
||||||
travelIndex: {
|
travelIndex: {
|
||||||
anySearchResult: 'vn-travel-index vn-tbody > a',
|
anySearchResult: 'vn-travel-index vn-tbody > a',
|
||||||
firstSearchResult: 'vn-travel-index vn-tbody > a:nth-child(1)',
|
firstSearchResult: 'vn-travel-index vn-tbody > a:nth-child(1)',
|
||||||
|
@ -1139,7 +1076,16 @@ export default {
|
||||||
landingDate: 'vn-travel-create vn-date-picker[ng-model="$ctrl.travel.landed"]',
|
landingDate: 'vn-travel-create vn-date-picker[ng-model="$ctrl.travel.landed"]',
|
||||||
warehouseOut: 'vn-travel-create vn-autocomplete[ng-model="$ctrl.travel.warehouseOutFk"]',
|
warehouseOut: 'vn-travel-create vn-autocomplete[ng-model="$ctrl.travel.warehouseOutFk"]',
|
||||||
warehouseIn: 'vn-travel-create vn-autocomplete[ng-model="$ctrl.travel.warehouseInFk"]',
|
warehouseIn: 'vn-travel-create vn-autocomplete[ng-model="$ctrl.travel.warehouseInFk"]',
|
||||||
save: 'vn-travel-create vn-submit > button'
|
save: 'vn-travel-create vn-submit > button',
|
||||||
|
generalSearchFilter: 'vn-travel-search-panel vn-textfield[ng-model="$ctrl.search"]',
|
||||||
|
agencyFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.agencyModeFk"]',
|
||||||
|
warehouseOutFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.warehouseOutFk"]',
|
||||||
|
warehouseInFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.warehouseInFk"]',
|
||||||
|
scopeDaysFilter: 'vn-travel-search-panel vn-input-number[ng-model="$ctrl.filter.scopeDays"]',
|
||||||
|
continentFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.continent"]',
|
||||||
|
totalEntriesFilter: 'vn-travel-search-panel vn-input-number[ng-model="$ctrl.totalEntries"]',
|
||||||
|
chip: 'vn-travel-search-panel vn-chip > vn-icon',
|
||||||
|
|
||||||
},
|
},
|
||||||
travelExtraCommunity: {
|
travelExtraCommunity: {
|
||||||
anySearchResult: 'vn-travel-extra-community > vn-card div > tbody > tr[ng-attr-id="{{::travel.id}}"]',
|
anySearchResult: 'vn-travel-extra-community > vn-card div > tbody > tr[ng-attr-id="{{::travel.id}}"]',
|
||||||
|
@ -1220,22 +1166,6 @@ export default {
|
||||||
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
|
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
|
||||||
anyBuyLine: 'vn-entry-summary tr.dark-row'
|
anyBuyLine: 'vn-entry-summary tr.dark-row'
|
||||||
},
|
},
|
||||||
entryBasicData: {
|
|
||||||
reference: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.reference"]',
|
|
||||||
invoiceNumber: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.invoiceNumber"]',
|
|
||||||
notes: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.notes"]',
|
|
||||||
observations: 'vn-entry-basic-data vn-textarea[ng-model="$ctrl.entry.observation"]',
|
|
||||||
supplier: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]',
|
|
||||||
currency: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.currencyFk"]',
|
|
||||||
commission: 'vn-entry-basic-data vn-input-number[ng-model="$ctrl.entry.commission"]',
|
|
||||||
company: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.companyFk"]',
|
|
||||||
ordered: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isOrdered"]',
|
|
||||||
confirmed: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isConfirmed"]',
|
|
||||||
inventory: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isExcludedFromAvailable"]',
|
|
||||||
raid: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isRaid"]',
|
|
||||||
booked: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isBooked"]',
|
|
||||||
save: 'vn-entry-basic-data button[type=submit]',
|
|
||||||
},
|
|
||||||
entryDescriptor: {
|
entryDescriptor: {
|
||||||
agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(1) span',
|
agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(1) span',
|
||||||
travelsQuicklink: 'vn-entry-descriptor vn-quick-link[icon="local_airport"] > a',
|
travelsQuicklink: 'vn-entry-descriptor vn-quick-link[icon="local_airport"] > a',
|
||||||
|
@ -1326,18 +1256,6 @@ export default {
|
||||||
notes: 'vn-supplier-basic-data vn-textarea[ng-model="$ctrl.supplier.note"]',
|
notes: 'vn-supplier-basic-data vn-textarea[ng-model="$ctrl.supplier.note"]',
|
||||||
saveButton: 'vn-supplier-basic-data button[type="submit"]',
|
saveButton: 'vn-supplier-basic-data button[type="submit"]',
|
||||||
},
|
},
|
||||||
supplierFiscalData: {
|
|
||||||
socialName: 'vn-supplier-fiscal-data vn-textfield[ng-model="$ctrl.supplier.name"]',
|
|
||||||
taxNumber: 'vn-supplier-fiscal-data vn-textfield[ng-model="$ctrl.supplier.nif"]',
|
|
||||||
account: 'vn-supplier-fiscal-data vn-textfield[ng-model="$ctrl.supplier.account"]',
|
|
||||||
sageTaxType: 'vn-supplier-fiscal-data vn-autocomplete[ng-model="$ctrl.supplier.sageTaxTypeFk"]',
|
|
||||||
sageWihholding: 'vn-supplier-fiscal-data vn-autocomplete[ng-model="$ctrl.supplier.sageWithholdingFk"]',
|
|
||||||
postCode: 'vn-supplier-fiscal-data vn-datalist[ng-model="$ctrl.supplier.postCode"]',
|
|
||||||
city: 'vn-supplier-fiscal-data vn-datalist[ng-model="$ctrl.supplier.city"]',
|
|
||||||
province: 'vn-supplier-fiscal-data vn-autocomplete[ng-model="$ctrl.supplier.provinceFk"]',
|
|
||||||
country: 'vn-supplier-fiscal-data vn-autocomplete[ng-model="$ctrl.supplier.countryFk"]',
|
|
||||||
saveButton: 'vn-supplier-fiscal-data button[type="submit"]',
|
|
||||||
},
|
|
||||||
supplierBillingData: {
|
supplierBillingData: {
|
||||||
payMethod: 'vn-supplier-billing-data vn-autocomplete[ng-model="$ctrl.supplier.payMethodFk"]',
|
payMethod: 'vn-supplier-billing-data vn-autocomplete[ng-model="$ctrl.supplier.payMethodFk"]',
|
||||||
payDem: 'vn-supplier-billing-data vn-autocomplete[ng-model="$ctrl.supplier.payDemFk"]',
|
payDem: 'vn-supplier-billing-data vn-autocomplete[ng-model="$ctrl.supplier.payDemFk"]',
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue