Merge branch 'dev' into 3946-permisos
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
commit
618db1661b
|
@ -62,13 +62,13 @@ pipeline {
|
|||
}
|
||||
}
|
||||
}
|
||||
// stage('Backend') {
|
||||
// steps {
|
||||
// nodejs('node-v14') {
|
||||
// sh 'gulp launchBackTest --ci'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
stage('Backend') {
|
||||
steps {
|
||||
nodejs('node-v14') {
|
||||
sh 'npm run test:back:ci'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build') {
|
||||
|
|
|
@ -54,17 +54,17 @@ $ gulp docker
|
|||
|
||||
For client-side unit tests run from project's root.
|
||||
```
|
||||
$ jest
|
||||
$ npm run test:front
|
||||
```
|
||||
|
||||
For server-side unit tests run from project's root.
|
||||
```
|
||||
$ gulp backTest
|
||||
$ npm run test:back
|
||||
```
|
||||
|
||||
For end-to-end tests run from project's root.
|
||||
```
|
||||
$ gulp e2e
|
||||
$ npm run test:e2e
|
||||
```
|
||||
|
||||
## Visual Studio Code extensions
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
const baseTime = null; // new Date(2022, 0, 19, 8, 0, 0, 0);
|
||||
if (baseTime) {
|
||||
jasmine.clock().install();
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
}
|
|
@ -5,17 +5,17 @@ module.exports = Self => {
|
|||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The user id',
|
||||
http: {source: 'path'}
|
||||
}, {
|
||||
arg: 'oldPassword',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'The old password',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'newPassword',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'The new password',
|
||||
required: true
|
||||
}
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('setPassword', {
|
||||
description: 'Sets the user password',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The user id',
|
||||
http: {source: 'path'}
|
||||
}, {
|
||||
arg: 'newPassword',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'The new password',
|
||||
required: true
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
const {models} = require('vn-loopback/server/server');
|
||||
|
||||
describe('account changePassword()', () => {
|
||||
it('should throw an error when old password is wrong', async() => {
|
||||
let req = app.models.Account.changePassword(null, 1, 'wrongOldPass', 'newPass');
|
||||
let err;
|
||||
await models.Account.changePassword(1, 'wrongPassword', 'nightmare.9999')
|
||||
.catch(error => err = error.sqlMessage);
|
||||
|
||||
await expectAsync(req).toBeRejected();
|
||||
expect(err).toBeDefined();
|
||||
expect(err).toEqual('Invalid password');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
const axios = require('axios');
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('send', {
|
||||
description: 'Send a RocketChat message',
|
||||
description: 'Creates a direct message in the chat model for a user or a channel',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'to',
|
||||
|
@ -31,39 +30,19 @@ module.exports = Self => {
|
|||
const recipient = to.replace('@', '');
|
||||
|
||||
if (sender.name != recipient) {
|
||||
await sendMessage(sender, to, message);
|
||||
await models.Chat.create({
|
||||
senderFk: sender.id,
|
||||
recipient: to,
|
||||
dated: new Date(),
|
||||
checkUserStatus: 0,
|
||||
message: message,
|
||||
status: 0,
|
||||
attempts: 0
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
async function sendMessage(sender, channel, message) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
return new Promise(resolve => {
|
||||
return resolve({
|
||||
statusCode: 200,
|
||||
message: 'Fake notification sent'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const login = await Self.getServiceAuth();
|
||||
const avatar = `${login.host}/avatar/${sender.name}`;
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'X-Auth-Token': login.auth.token,
|
||||
'X-User-Id': login.auth.userId
|
||||
},
|
||||
};
|
||||
|
||||
return axios.post(`${login.api}/chat.postMessage`, {
|
||||
'channel': channel,
|
||||
'avatar': avatar,
|
||||
'alias': sender.nickname,
|
||||
'text': message
|
||||
}, options);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
const axios = require('axios');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('sendCheckingPresence', {
|
||||
description: 'Sends a RocketChat message to a connected user or department channel',
|
||||
description: 'Creates a message in the chat model checking the user status',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'workerId',
|
||||
|
@ -36,6 +34,7 @@ module.exports = Self => {
|
|||
|
||||
const models = Self.app.models;
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
const sender = await models.Account.findById(userId);
|
||||
const recipient = await models.Account.findById(recipientId, null, myOptions);
|
||||
|
||||
// Prevent sending messages to yourself
|
||||
|
@ -44,54 +43,16 @@ module.exports = Self => {
|
|||
if (!recipient)
|
||||
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);
|
||||
|
||||
const {data} = await Self.getUserStatus(recipient.name);
|
||||
if (data) {
|
||||
if (data.status === 'offline' || data.status === 'busy') {
|
||||
// Send message to department room
|
||||
const workerDepartment = await models.WorkerDepartment.findById(recipientId, {
|
||||
include: {
|
||||
relation: 'department'
|
||||
}
|
||||
}, myOptions);
|
||||
const department = workerDepartment && workerDepartment.department();
|
||||
const channelName = department && department.chatName;
|
||||
await models.Chat.create({
|
||||
senderFk: sender.id,
|
||||
recipient: `@${recipient.name}`,
|
||||
dated: new Date(),
|
||||
checkUserStatus: 1,
|
||||
message: message,
|
||||
status: 0,
|
||||
attempts: 0
|
||||
});
|
||||
|
||||
if (channelName)
|
||||
return Self.send(ctx, `#${channelName}`, `@${recipient.name} ➔ ${message}`);
|
||||
else
|
||||
return Self.send(ctx, `@${recipient.name}`, message);
|
||||
} else
|
||||
return Self.send(ctx, `@${recipient.name}`, message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current user status on Rocketchat
|
||||
*
|
||||
* @param {string} username - The recipient user name
|
||||
* @return {Promise} - The request promise
|
||||
*/
|
||||
Self.getUserStatus = async function getUserStatus(username) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
return new Promise(resolve => {
|
||||
return resolve({
|
||||
data: {
|
||||
status: 'online'
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const login = await Self.getServiceAuth();
|
||||
|
||||
const options = {
|
||||
params: {username},
|
||||
headers: {
|
||||
'X-Auth-Token': login.auth.token,
|
||||
'X-User-Id': login.auth.userId
|
||||
},
|
||||
};
|
||||
|
||||
return axios.get(`${login.api}/users.getStatus`, options);
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
const axios = require('axios');
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('sendQueued', {
|
||||
description: 'Send a RocketChat message',
|
||||
accessType: 'WRITE',
|
||||
accepts: [],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/sendQueued`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.sendQueued = async() => {
|
||||
const models = Self.app.models;
|
||||
const maxAttempts = 3;
|
||||
const sentStatus = 1;
|
||||
const errorStatus = 2;
|
||||
|
||||
const chats = await models.Chat.find({
|
||||
where: {
|
||||
status: {neq: sentStatus},
|
||||
attempts: {lt: maxAttempts}
|
||||
}
|
||||
});
|
||||
|
||||
for (let chat of chats) {
|
||||
if (chat.checkUserStatus) {
|
||||
try {
|
||||
await Self.sendCheckingUserStatus(chat);
|
||||
await updateChat(chat, sentStatus);
|
||||
} catch (error) {
|
||||
await updateChat(chat, errorStatus);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
|
||||
await updateChat(chat, sentStatus);
|
||||
} catch (error) {
|
||||
await updateChat(chat, errorStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check user status in Rocket
|
||||
*
|
||||
* @param {object} chat - The sender id
|
||||
* @return {Promise} - The request promise
|
||||
*/
|
||||
Self.sendCheckingUserStatus = async function sendCheckingUserStatus(chat) {
|
||||
const models = Self.app.models;
|
||||
|
||||
const recipientName = chat.recipient.slice(1);
|
||||
const recipient = await models.Account.findOne({
|
||||
where: {
|
||||
name: recipientName
|
||||
}
|
||||
});
|
||||
|
||||
const {data} = await Self.getUserStatus(recipient.name);
|
||||
if (data) {
|
||||
if (data.status === 'offline' || data.status === 'busy') {
|
||||
// Send message to department room
|
||||
const workerDepartment = await models.WorkerDepartment.findById(recipient.id, {
|
||||
include: {
|
||||
relation: 'department'
|
||||
}
|
||||
});
|
||||
const department = workerDepartment && workerDepartment.department();
|
||||
const channelName = department && department.chatName;
|
||||
|
||||
if (channelName)
|
||||
return Self.sendMessage(chat.senderFk, `#${channelName}`, `@${recipient.name} ➔ ${message}`);
|
||||
else
|
||||
return Self.sendMessage(chat.senderFk, `@${recipient.name}`, chat.message);
|
||||
} else
|
||||
return Self.sendMessage(chat.senderFk, `@${recipient.name}`, chat.message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a rocket message
|
||||
*
|
||||
* @param {object} senderFk - The sender id
|
||||
* @param {string} recipient - The user (@) or channel (#) to send the message
|
||||
* @param {string} message - The message to send
|
||||
* @return {Promise} - The request promise
|
||||
*/
|
||||
Self.sendMessage = async function sendMessage(senderFk, recipient, message) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
return new Promise(resolve => {
|
||||
return resolve({
|
||||
statusCode: 200,
|
||||
message: 'Fake notification sent'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const models = Self.app.models;
|
||||
const sender = await models.Account.findById(senderFk);
|
||||
|
||||
const login = await Self.getServiceAuth();
|
||||
const avatar = `${login.host}/avatar/${sender.name}`;
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'X-Auth-Token': login.auth.token,
|
||||
'X-User-Id': login.auth.userId
|
||||
},
|
||||
};
|
||||
|
||||
return axios.post(`${login.api}/chat.postMessage`, {
|
||||
'channel': recipient,
|
||||
'avatar': avatar,
|
||||
'alias': sender.nickname,
|
||||
'text': message
|
||||
}, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update status and attempts of a chat
|
||||
*
|
||||
* @param {object} chat - The chat
|
||||
* @param {string} status - The new status
|
||||
* @return {Promise} - The request promise
|
||||
*/
|
||||
async function updateChat(chat, status) {
|
||||
return chat.updateAttributes({
|
||||
status: status,
|
||||
attempts: ++chat.attempts
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current user status on Rocketchat
|
||||
*
|
||||
* @param {string} username - The recipient user name
|
||||
* @return {Promise} - The request promise
|
||||
*/
|
||||
Self.getUserStatus = async function getUserStatus(username) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
return new Promise(resolve => {
|
||||
return resolve({
|
||||
data: {
|
||||
status: 'online'
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const login = await Self.getServiceAuth();
|
||||
|
||||
const options = {
|
||||
params: {username},
|
||||
headers: {
|
||||
'X-Auth-Token': login.auth.token,
|
||||
'X-User-Id': login.auth.userId
|
||||
},
|
||||
};
|
||||
|
||||
return axios.get(`${login.api}/users.getStatus`, options);
|
||||
};
|
||||
};
|
|
@ -1,14 +1,14 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('Chat send()', () => {
|
||||
it('should return a "Fake notification sent" as response', async() => {
|
||||
it('should return true as response', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 1}}};
|
||||
let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something');
|
||||
|
||||
expect(response).toEqual(true);
|
||||
});
|
||||
|
||||
it('should retrun false as response', async() => {
|
||||
it('should return false as response', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 18}}};
|
||||
let response = await app.models.Chat.send(ctx, '@salesPerson', 'I changed something');
|
||||
|
||||
|
|
|
@ -1,58 +1,21 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Chat sendCheckingPresence()', () => {
|
||||
const today = new Date();
|
||||
today.setHours(6, 0);
|
||||
const ctx = {req: {accessToken: {userId: 1}}};
|
||||
const chatModel = models.Chat;
|
||||
const departmentId = 23;
|
||||
const workerId = 1107;
|
||||
it('should return true as response', async() => {
|
||||
const workerId = 1107;
|
||||
|
||||
it(`should call to send() method with "@HankPym" as recipient argument`, async() => {
|
||||
spyOn(chatModel, 'send').and.callThrough();
|
||||
spyOn(chatModel, 'getUserStatus').and.returnValue(
|
||||
new Promise(resolve => {
|
||||
return resolve({
|
||||
data: {
|
||||
status: 'online'
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
let ctx = {req: {accessToken: {userId: 1}}};
|
||||
let response = await models.Chat.sendCheckingPresence(ctx, workerId, 'I changed something');
|
||||
|
||||
await chatModel.sendCheckingPresence(ctx, workerId, 'I changed something');
|
||||
|
||||
expect(chatModel.send).toHaveBeenCalledWith(ctx, '@HankPym', 'I changed something');
|
||||
expect(response).toEqual(true);
|
||||
});
|
||||
|
||||
it(`should call to send() method with "#cooler" as recipient argument`, async() => {
|
||||
spyOn(chatModel, 'send').and.callThrough();
|
||||
spyOn(chatModel, 'getUserStatus').and.returnValue(
|
||||
new Promise(resolve => {
|
||||
return resolve({
|
||||
data: {
|
||||
status: 'offline'
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
it('should return false as response', async() => {
|
||||
const salesPersonId = 18;
|
||||
|
||||
const tx = await models.Claim.beginTransaction({});
|
||||
let ctx = {req: {accessToken: {userId: 18}}};
|
||||
let response = await models.Chat.sendCheckingPresence(ctx, salesPersonId, 'I changed something');
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const department = await models.Department.findById(departmentId, null, options);
|
||||
await department.updateAttribute('chatName', 'cooler');
|
||||
|
||||
await chatModel.sendCheckingPresence(ctx, workerId, 'I changed something');
|
||||
|
||||
expect(chatModel.send).toHaveBeenCalledWith(ctx, '#cooler', '@HankPym ➔ I changed something');
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
expect(response).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Chat sendCheckingPresence()', () => {
|
||||
const today = new Date();
|
||||
today.setHours(6, 0);
|
||||
const chatModel = models.Chat;
|
||||
|
||||
it(`should call to sendCheckingUserStatus()`, async() => {
|
||||
spyOn(chatModel, 'sendCheckingUserStatus').and.callThrough();
|
||||
|
||||
const chat = {
|
||||
checkUserStatus: 1,
|
||||
status: 0,
|
||||
attempts: 0
|
||||
};
|
||||
|
||||
await chatModel.destroyAll();
|
||||
await chatModel.create(chat);
|
||||
|
||||
await chatModel.sendQueued();
|
||||
|
||||
expect(chatModel.sendCheckingUserStatus).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should call to sendMessage() method`, async() => {
|
||||
spyOn(chatModel, 'sendMessage').and.callThrough();
|
||||
|
||||
const chat = {
|
||||
checkUserStatus: 0,
|
||||
status: 0,
|
||||
attempts: 0
|
||||
};
|
||||
|
||||
await chatModel.destroyAll();
|
||||
await chatModel.create(chat);
|
||||
|
||||
await chatModel.sendQueued();
|
||||
|
||||
expect(chatModel.sendMessage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('setSaleQuantity', {
|
||||
Self.remoteMethod('setSaleQuantity', {
|
||||
description: 'Update sale quantity',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
|
@ -24,11 +24,13 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.setSaleQuantity = async ctx => {
|
||||
const args = ctx.args;
|
||||
Self.setSaleQuantity = async(saleId, quantity) => {
|
||||
const models = Self.app.models;
|
||||
|
||||
const sale = await models.Sale.findById(args.saleId);
|
||||
return await sale.updateAttribute('quantity', args.quantity);
|
||||
const sale = await models.Sale.findById(saleId);
|
||||
return await sale.updateAttributes({
|
||||
originalQuantity: sale.quantity,
|
||||
quantity: quantity
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
// #3400 analizar que hacer con rutas de back colletion
|
||||
xdescribe('newCollection()', () => {
|
||||
it('return a new collection', async() => {
|
||||
describe('newCollection()', () => {
|
||||
it('should return a new collection', async() => {
|
||||
pending('#3400 analizar que hacer con rutas de back collection');
|
||||
let ctx = {req: {accessToken: {userId: 1106}}};
|
||||
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1);
|
||||
|
||||
|
|
|
@ -5,19 +5,12 @@ describe('setSaleQuantity()', () => {
|
|||
const saleId = 30;
|
||||
const newQuantity = 10;
|
||||
|
||||
const ctx = {
|
||||
args: {
|
||||
saleId: saleId,
|
||||
quantity: newQuantity
|
||||
}
|
||||
};
|
||||
|
||||
const originalSale = await models.Sale.findById(saleId);
|
||||
|
||||
await models.Collection.setSaleQuantity(ctx);
|
||||
await models.Collection.setSaleQuantity(saleId, newQuantity);
|
||||
const updateSale = await models.Sale.findById(saleId);
|
||||
|
||||
expect(updateSale.quantity).toBeLessThan(originalSale.quantity);
|
||||
expect(updateSale.originalQuantity).toEqual(originalSale.quantity);
|
||||
expect(updateSale.quantity).toEqual(newQuantity);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('deleteTrashFiles', {
|
||||
description: 'Deletes files that have trash type',
|
||||
accessType: 'WRITE',
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/deleteTrashFiles`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.deleteTrashFiles = async(options) => {
|
||||
const tx = await Self.beginTransaction({});
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction)
|
||||
myOptions.transaction = tx;
|
||||
|
||||
try {
|
||||
const models = Self.app.models;
|
||||
const DmsContainer = models.DmsContainer;
|
||||
|
||||
const trashDmsType = await models.DmsType.findOne({
|
||||
where: {code: 'trash'}
|
||||
}, myOptions);
|
||||
|
||||
const dmsToDelete = await models.Dms.find({
|
||||
where: {
|
||||
dmsTypeFk: trashDmsType.id
|
||||
}
|
||||
}, myOptions);
|
||||
|
||||
for (let dms of dmsToDelete) {
|
||||
const pathHash = DmsContainer.getHash(dms.id);
|
||||
const dmsContainer = await DmsContainer.container(pathHash);
|
||||
const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file);
|
||||
await fs.unlink(dstFile);
|
||||
await dms.destroy(myOptions);
|
||||
}
|
||||
if (tx) await tx.commit();
|
||||
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE bucket
|
||||
INTO TABLE `edi`.`bucket`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE bucket_type
|
||||
INTO TABLE `edi`.`bucket_type`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE `feature`
|
||||
INTO TABLE `edi`.`feature`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE genus
|
||||
INTO TABLE `edi`.`genus`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE item
|
||||
INTO TABLE `edi`.`item`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE `item_feature`
|
||||
INTO TABLE `edi`.`item_feature`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE item_group
|
||||
INTO TABLE `edi`.`item_group`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE plant
|
||||
INTO TABLE `edi`.`plant`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE specie
|
||||
INTO TABLE `edi`.`specie`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE edi.supplier
|
||||
INTO TABLE `edi`.`supplier`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12, @col13, @col14, @col15, @col16, @col17, @col18, @col19, @col20)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE `type`
|
||||
INTO TABLE `edi`.`type`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7)
|
||||
SET
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LOAD DATA LOCAL INFILE ?
|
||||
INTO TABLE `value`
|
||||
INTO TABLE `edi`.`value`
|
||||
FIELDS TERMINATED BY ';'
|
||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7)
|
||||
SET
|
||||
|
|
|
@ -19,137 +19,218 @@ module.exports = Self => {
|
|||
Self.updateData = async() => {
|
||||
const models = Self.app.models;
|
||||
|
||||
// Get files checksum
|
||||
const files = await Self.rawSql('SELECT name, checksum, keyValue FROM edi.fileConfig');
|
||||
|
||||
const updatableFiles = [];
|
||||
for (const file of files) {
|
||||
const fileChecksum = await getChecksum(file);
|
||||
|
||||
if (file.checksum != fileChecksum) {
|
||||
updatableFiles.push({
|
||||
name: file.name,
|
||||
checksum: fileChecksum
|
||||
});
|
||||
} else
|
||||
console.debug(`File already updated, skipping...`);
|
||||
}
|
||||
|
||||
if (updatableFiles.length === 0)
|
||||
return false;
|
||||
|
||||
// Download files
|
||||
const container = await models.TempContainer.container('edi');
|
||||
const tempPath = path.join(container.client.root, container.name);
|
||||
|
||||
const [ftpConfig] = await Self.rawSql('SELECT host, user, password FROM edi.ftpConfig');
|
||||
console.debug(`Openning FTP connection to ${ftpConfig.host}...\n`);
|
||||
|
||||
const FtpClient = require('ftps');
|
||||
const ftpClient = new FtpClient({
|
||||
host: ftpConfig.host,
|
||||
username: ftpConfig.user,
|
||||
password: ftpConfig.password,
|
||||
procotol: 'ftp'
|
||||
});
|
||||
|
||||
const files = await Self.rawSql('SELECT fileName, toTable, file, updated FROM edi.fileConfig');
|
||||
|
||||
let remoteFile;
|
||||
let tempDir;
|
||||
let tempFile;
|
||||
for (const file of files) {
|
||||
|
||||
const fileNames = updatableFiles.map(file => file.name);
|
||||
|
||||
const tables = await Self.rawSql(`
|
||||
SELECT fileName, toTable, file
|
||||
FROM edi.tableConfig
|
||||
WHERE file IN (?)`, [fileNames]);
|
||||
|
||||
for (const table of tables) {
|
||||
const fileName = table.file;
|
||||
|
||||
console.debug(`Downloading file ${fileName}...`);
|
||||
|
||||
remoteFile = `codes/${fileName}.ZIP`;
|
||||
tempDir = `${tempPath}/${fileName}`;
|
||||
tempFile = `${tempPath}/${fileName}.zip`;
|
||||
|
||||
try {
|
||||
const fileName = file.file;
|
||||
|
||||
console.debug(`Downloading file ${fileName}...`);
|
||||
|
||||
remoteFile = `codes/${fileName}.ZIP`;
|
||||
tempDir = `${tempPath}/${fileName}`;
|
||||
tempFile = `${tempPath}/${fileName}.zip`;
|
||||
|
||||
await extractFile({
|
||||
ftpClient: ftpClient,
|
||||
file: file,
|
||||
paths: {
|
||||
remoteFile: remoteFile,
|
||||
tempDir: tempDir,
|
||||
tempFile: tempFile
|
||||
}
|
||||
});
|
||||
await fs.readFile(tempFile);
|
||||
} catch (error) {
|
||||
if (fs.existsSync(tempFile))
|
||||
await fs.unlink(tempFile);
|
||||
|
||||
await fs.rmdir(tempDir, {recursive: true});
|
||||
console.error(error);
|
||||
if (error.code === 'ENOENT') {
|
||||
const downloadOutput = await downloadFile(remoteFile, tempFile);
|
||||
if (downloadOutput.error)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
console.debug(`Extracting file ${fileName}...`);
|
||||
await extractFile(tempFile, tempDir);
|
||||
|
||||
console.debug(`Updating table ${table.toTable}...`);
|
||||
await dumpData(tempDir, table);
|
||||
}
|
||||
|
||||
// Update files checksum
|
||||
for (const file of updatableFiles) {
|
||||
await Self.rawSql(`
|
||||
UPDATE edi.fileConfig
|
||||
SET checksum = ?
|
||||
WHERE name = ?`,
|
||||
[file.checksum, file.name]);
|
||||
}
|
||||
|
||||
// Clean files
|
||||
try {
|
||||
await fs.remove(tempPath);
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT')
|
||||
throw e;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
async function extractFile({ftpClient, file, paths}) {
|
||||
// Download the zip file
|
||||
ftpClient.get(paths.remoteFile, paths.tempFile);
|
||||
let ftpClient;
|
||||
async function getFtpClient() {
|
||||
if (!ftpClient) {
|
||||
const [ftpConfig] = await Self.rawSql('SELECT host, user, password FROM edi.ftpConfig');
|
||||
console.debug(`Openning FTP connection to ${ftpConfig.host}...\n`);
|
||||
|
||||
// Execute download command
|
||||
ftpClient.exec(async(err, response) => {
|
||||
if (response.error) {
|
||||
console.debug(`Error downloading file... ${response.error}`);
|
||||
return;
|
||||
}
|
||||
const FtpClient = require('ftps');
|
||||
|
||||
const AdmZip = require('adm-zip');
|
||||
const zip = new AdmZip(paths.tempFile);
|
||||
const entries = zip.getEntries();
|
||||
ftpClient = new FtpClient({
|
||||
host: ftpConfig.host,
|
||||
username: ftpConfig.user,
|
||||
password: ftpConfig.password,
|
||||
procotol: 'ftp'
|
||||
});
|
||||
}
|
||||
|
||||
zip.extractAllTo(paths.tempDir, false);
|
||||
return ftpClient;
|
||||
}
|
||||
|
||||
if (fs.existsSync(paths.tempFile))
|
||||
await fs.unlink(paths.tempFile);
|
||||
async function getChecksum(file) {
|
||||
const ftpClient = await getFtpClient();
|
||||
console.debug(`Checking checksum for file ${file.name}...`);
|
||||
|
||||
await dumpData({file, entries, paths});
|
||||
ftpClient.cat(`codes/${file.name}.txt`);
|
||||
|
||||
await fs.rmdir(paths.tempDir, {recursive: true});
|
||||
const response = await new Promise((resolve, reject) => {
|
||||
ftpClient.exec((err, response) => {
|
||||
if (response.error) {
|
||||
console.debug(`Error downloading checksum file... ${response.error}`);
|
||||
reject(err);
|
||||
}
|
||||
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
|
||||
if (response && response.data) {
|
||||
const fileContents = response.data;
|
||||
const rows = fileContents.split('\n');
|
||||
const row = rows[4];
|
||||
const columns = row.split(/\s+/);
|
||||
|
||||
let fileChecksum;
|
||||
if (file.keyValue)
|
||||
fileChecksum = columns[1];
|
||||
|
||||
if (!file.keyValue)
|
||||
fileChecksum = columns[0];
|
||||
|
||||
return fileChecksum;
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadFile(remoteFile, tempFile) {
|
||||
const ftpClient = await getFtpClient();
|
||||
|
||||
ftpClient.get(remoteFile, tempFile);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
ftpClient.exec((err, response) => {
|
||||
if (response.error) {
|
||||
console.debug(`Error downloading file... ${response.error}`);
|
||||
reject(err);
|
||||
}
|
||||
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function dumpData({file, entries, paths}) {
|
||||
const toTable = file.toTable;
|
||||
const baseName = file.fileName;
|
||||
async function extractFile(tempFile, tempDir) {
|
||||
const JSZip = require('jszip');
|
||||
|
||||
for (const zipEntry of entries) {
|
||||
const entryName = zipEntry.entryName;
|
||||
console.log(`Reading file ${entryName}...`);
|
||||
try {
|
||||
await fs.mkdir(tempDir);
|
||||
} catch (error) {
|
||||
if (error.code !== 'EEXIST')
|
||||
throw e;
|
||||
}
|
||||
|
||||
const startIndex = (entryName.length - 10);
|
||||
const endIndex = (entryName.length - 4);
|
||||
const dateString = entryName.substring(startIndex, endIndex);
|
||||
const lastUpdated = new Date();
|
||||
const fileStream = await fs.readFile(tempFile);
|
||||
if (fileStream) {
|
||||
const zip = new JSZip();
|
||||
const zipContents = await zip.loadAsync(fileStream);
|
||||
|
||||
// Format string date to a date object
|
||||
let updated = null;
|
||||
if (file.updated) {
|
||||
updated = new Date(file.updated);
|
||||
updated.setHours(0, 0, 0, 0);
|
||||
if (!zipContents) return;
|
||||
|
||||
const fileNames = Object.keys(zipContents.files);
|
||||
|
||||
for (const fileName of fileNames) {
|
||||
const fileContent = await zip.file(fileName).async('nodebuffer');
|
||||
const dest = path.join(tempDir, fileName);
|
||||
await fs.writeFile(dest, fileContent);
|
||||
}
|
||||
|
||||
lastUpdated.setFullYear(`20${dateString.substring(4, 6)}`);
|
||||
lastUpdated.setMonth(parseInt(dateString.substring(2, 4)) - 1);
|
||||
lastUpdated.setDate(dateString.substring(0, 2));
|
||||
lastUpdated.setHours(0, 0, 0, 0);
|
||||
|
||||
if (updated && lastUpdated <= updated) {
|
||||
console.debug(`Table ${toTable} already updated, skipping...`);
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log('Dumping data...');
|
||||
const templatePath = path.join(__dirname, `./sql/${toTable}.sql`);
|
||||
const sqlTemplate = fs.readFileSync(templatePath, 'utf8');
|
||||
|
||||
const rawPath = path.join(paths.tempDir, entryName);
|
||||
|
||||
try {
|
||||
const tx = await Self.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
await Self.rawSql(`DELETE FROM edi.${toTable}`, null, options);
|
||||
await Self.rawSql(sqlTemplate, [rawPath], options);
|
||||
await Self.rawSql(`
|
||||
UPDATE edi.fileConfig
|
||||
SET updated = ?
|
||||
WHERE fileName = ?
|
||||
`, [lastUpdated, baseName], options);
|
||||
|
||||
tx.commit();
|
||||
} catch (error) {
|
||||
tx.rollback();
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.log(`Updated table ${toTable}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
async function dumpData(tempDir, table) {
|
||||
const toTable = table.toTable;
|
||||
const baseName = table.fileName;
|
||||
|
||||
const tx = await Self.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const tableName = `edi.${toTable}`;
|
||||
await Self.rawSql(`DELETE FROM ??`, [tableName], options);
|
||||
|
||||
const dirFiles = await fs.readdir(tempDir);
|
||||
const files = dirFiles.filter(file => file.startsWith(baseName));
|
||||
|
||||
for (const file of files) {
|
||||
console.log(`Dumping data from file ${file}...`);
|
||||
|
||||
const templatePath = path.join(__dirname, `./sql/${toTable}.sql`);
|
||||
const sqlTemplate = await fs.readFile(templatePath, 'utf8');
|
||||
const filePath = path.join(tempDir, file);
|
||||
|
||||
await Self.rawSql(sqlTemplate, [filePath], options);
|
||||
await Self.rawSql(`
|
||||
UPDATE edi.tableConfig
|
||||
SET updated = ?
|
||||
WHERE fileName = ?
|
||||
`, [new Date(), baseName], options);
|
||||
}
|
||||
|
||||
tx.commit();
|
||||
} catch (error) {
|
||||
tx.rollback();
|
||||
throw error;
|
||||
}
|
||||
console.log(`Updated table ${toTable}\n`);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -68,6 +68,12 @@
|
|||
"Language": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"MachineWorker": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"MobileAppVersionControl": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Module": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"type": "date"
|
||||
},
|
||||
"image": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
},
|
||||
"maxAmount": {
|
||||
"type": "number"
|
||||
},
|
||||
"daysInFuture": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"acls": [{
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "MobileAppVersionControl",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "vn.mobileAppVersionControl"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"appName": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"isVersionCritical": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"bic": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -8,35 +8,35 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"bank": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"account": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"accountingTypeFk": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true,
|
||||
"mysql": {
|
||||
"columnName": "cash"
|
||||
}
|
||||
},
|
||||
"entityFk": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"isActive": {
|
||||
"type": "Boolean",
|
||||
"type": "boolean",
|
||||
"required": true
|
||||
},
|
||||
"currencyFk": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -10,20 +10,20 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"host": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"api": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"user": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"acls": [{
|
||||
|
|
|
@ -3,4 +3,5 @@ module.exports = Self => {
|
|||
require('../methods/chat/send')(Self);
|
||||
require('../methods/chat/sendCheckingPresence')(Self);
|
||||
require('../methods/chat/notifyIssues')(Self);
|
||||
require('../methods/chat/sendQueued')(Self);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,39 @@
|
|||
{
|
||||
"name": "Chat",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "chat"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"senderFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"recipient": {
|
||||
"type": "string"
|
||||
},
|
||||
"dated": {
|
||||
"type": "date"
|
||||
},
|
||||
"checkUserStatus": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"attempts": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"acls": [{
|
||||
"property": "validations",
|
||||
"accessType": "EXECUTE",
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"code": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"expired": {
|
||||
"type": "date"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
@ -21,7 +21,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"isUeeMember": {
|
||||
"type": "Boolean"
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"forceId": false
|
||||
},
|
||||
"date": {
|
||||
"type": "Date"
|
||||
"type": "date"
|
||||
},
|
||||
"m3":{
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"warehouseFk":{
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
|
|
@ -5,6 +5,7 @@ module.exports = Self => {
|
|||
require('../methods/dms/uploadFile')(Self);
|
||||
require('../methods/dms/removeFile')(Self);
|
||||
require('../methods/dms/updateFile')(Self);
|
||||
require('../methods/dms/deleteTrashFiles')(Self);
|
||||
|
||||
Self.checkRole = async function(ctx, id) {
|
||||
const models = Self.app.models;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
@ -36,7 +36,7 @@
|
|||
"type": "boolean"
|
||||
},
|
||||
"created": {
|
||||
"type": "Date"
|
||||
"type": "date"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"properties": {
|
||||
"userFk": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"email": {
|
||||
|
|
|
@ -8,20 +8,20 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"width": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"height": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"crop": {
|
||||
"type": "Boolean",
|
||||
"type": "boolean",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,32 +8,32 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"name": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"desc": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"maxWidth": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"maxHeight": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"model": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"property": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "MachineWorker",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "vn.machineWorker"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"workerFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"machineFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"inTime": {
|
||||
"type": "date",
|
||||
"mysql": {
|
||||
"columnName": "inTimed"
|
||||
}
|
||||
},
|
||||
"outTime": {
|
||||
"type": "date",
|
||||
"mysql": {
|
||||
"columnName": "outTimed"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
"properties": {
|
||||
"code": {
|
||||
"id": true,
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier",
|
||||
"mysql": {
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"name": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -9,18 +9,18 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"userFk": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"tableCode": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"configuration": {
|
||||
"type": "Object"
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -9,40 +9,40 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"forceId": false
|
||||
},
|
||||
"originFk": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"userFk": {
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"action": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"changedModel": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"oldInstance": {
|
||||
"type": "Object"
|
||||
"type": "object"
|
||||
},
|
||||
"newInstance": {
|
||||
"type": "Object"
|
||||
"type": "object"
|
||||
},
|
||||
"creationDate": {
|
||||
"type": "Date"
|
||||
"type": "date"
|
||||
},
|
||||
"changedModelId": {
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"changedModelValue": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"forceId": false
|
||||
},
|
||||
"username":{
|
||||
|
|
|
@ -10,17 +10,17 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"forceId": false
|
||||
},
|
||||
"name": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"isInventory": {
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"isManaged":{
|
||||
"type": "boolean"
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"verbose": true,
|
||||
"watch": [
|
||||
"back/**/*.js",
|
||||
"modules/**/*.js"
|
||||
],
|
||||
"ignore": [
|
||||
"modules/account/front/**/*",
|
||||
"modules/claim/front/**/*",
|
||||
"modules/client/front/**/*",
|
||||
"modules/entry/front/**/*",
|
||||
"modules/invoiceIn/front/**/*",
|
||||
"modules/invoiceOut/front/**/*",
|
||||
"modules/item/front/**/*",
|
||||
"modules/monitor/front/**/*",
|
||||
"modules/order/front/**/*",
|
||||
"modules/route/front/**/*",
|
||||
"modules/supplier/front/**/*",
|
||||
"modules/ticket/front/**/*",
|
||||
"modules/travel/front/**/*",
|
||||
"modules/worker/front/**/*",
|
||||
"modules/zone/front/**/*"
|
||||
]
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
require('require-yaml');
|
||||
const Docker = require('../db/docker.js');
|
||||
let dataSources = require('../loopback/server/datasources.json');
|
||||
|
||||
process.on('warning', warning => {
|
||||
console.log(warning.name);
|
||||
|
@ -6,34 +7,64 @@ process.on('warning', warning => {
|
|||
console.log(warning.stack);
|
||||
});
|
||||
|
||||
let verbose = false;
|
||||
async function test() {
|
||||
let isCI = false;
|
||||
|
||||
if (process.argv[2] === '--v')
|
||||
verbose = true;
|
||||
if (process.argv[2] === 'ci')
|
||||
isCI = true;
|
||||
|
||||
let Jasmine = require('jasmine');
|
||||
let jasmine = new Jasmine();
|
||||
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;
|
||||
const container = new Docker();
|
||||
|
||||
let serviceSpecs = [
|
||||
`${__dirname}/**/*[sS]pec.js`,
|
||||
`${__dirname}/../loopback/**/*[sS]pec.js`,
|
||||
`${__dirname}/../modules/*/back/**/*.[sS]pec.js`
|
||||
];
|
||||
await container.run(isCI);
|
||||
dataSources = JSON.parse(JSON.stringify(dataSources));
|
||||
|
||||
jasmine.loadConfig({
|
||||
spec_dir: '.',
|
||||
spec_files: serviceSpecs,
|
||||
helpers: []
|
||||
});
|
||||
Object.assign(dataSources.vn, {
|
||||
host: container.dbConf.host,
|
||||
port: container.dbConf.port
|
||||
});
|
||||
|
||||
jasmine.addReporter(new SpecReporter({
|
||||
spec: {
|
||||
// displayStacktrace: 'summary',
|
||||
displaySuccessful: verbose,
|
||||
displayFailedSpec: true,
|
||||
displaySpecDuration: true
|
||||
const bootOptions = {dataSources};
|
||||
const app = require('vn-loopback/server/server');
|
||||
app.boot(bootOptions);
|
||||
|
||||
const Jasmine = require('jasmine');
|
||||
const jasmine = new Jasmine();
|
||||
|
||||
const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
|
||||
jasmine.addReporter(new SpecReporter({
|
||||
spec: {
|
||||
displaySuccessful: isCI,
|
||||
displayPending: isCI
|
||||
},
|
||||
summary: {
|
||||
displayPending: false,
|
||||
}
|
||||
}));
|
||||
|
||||
if (isCI) {
|
||||
const JunitReporter = require('jasmine-reporters');
|
||||
jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
|
||||
|
||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
|
||||
}
|
||||
}));
|
||||
|
||||
jasmine.execute();
|
||||
const backSpecs = [
|
||||
'./back/**/*[sS]pec.js',
|
||||
'./loopback/**/*[sS]pec.js',
|
||||
'./modules/*/back/**/*.[sS]pec.js'
|
||||
];
|
||||
|
||||
jasmine.loadConfig({
|
||||
spec_dir: '.',
|
||||
spec_files: backSpecs,
|
||||
helpers: [],
|
||||
});
|
||||
|
||||
jasmine.exitOnCompletion = false;
|
||||
await jasmine.execute();
|
||||
if (app) await app.disconnect();
|
||||
if (container) await container.rm();
|
||||
console.log('app disconnected & container removed');
|
||||
}
|
||||
|
||||
test();
|
||||
|
|
|
@ -31,11 +31,13 @@ COPY \
|
|||
import-changes.sh \
|
||||
config.ini \
|
||||
dump/mysqlPlugins.sql \
|
||||
dump/mockDate.sql \
|
||||
dump/structure.sql \
|
||||
dump/dumpedFixtures.sql \
|
||||
./
|
||||
RUN gosu mysql docker-init.sh \
|
||||
&& docker-dump.sh mysqlPlugins \
|
||||
&& docker-dump.sh mockDate \
|
||||
&& docker-dump.sh structure \
|
||||
&& docker-dump.sh dumpedFixtures \
|
||||
&& gosu mysql docker-temp-stop.sh
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO `salix`.`ACL`(`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('ExpeditionState', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,5 @@
|
|||
INSERT INTO `salix`.`ACL`(`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('Expense', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||
|
||||
INSERT INTO `salix`.`ACL`(`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('Expense', '*', 'WRITE', 'ALLOW', 'ROLE', 'administrative');
|
|
@ -0,0 +1,5 @@
|
|||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('SupplierActivity', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('SupplierActivity', '*', 'WRITE', 'ALLOW', 'ROLE', 'administrative');
|
|
@ -1,14 +0,0 @@
|
|||
create table `vn`.`invoiceOut_queue`
|
||||
(
|
||||
invoiceFk int(10) unsigned not null,
|
||||
queued datetime default now() not null,
|
||||
printed datetime null,
|
||||
`status` VARCHAR(50) default '' null,
|
||||
constraint invoiceOut_queue_pk
|
||||
primary key (invoiceFk),
|
||||
constraint invoiceOut_queue_invoiceOut_id_fk
|
||||
foreign key (invoiceFk) references invoiceOut (id)
|
||||
on update cascade on delete cascade
|
||||
)
|
||||
comment 'Queue for PDF invoicing';
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
DROP PROCEDURE IF EXISTS vn.ticket_doRefund;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_doRefund`(IN vOriginTicket INT, OUT vNewTicket INT)
|
||||
BEGIN
|
||||
|
||||
DECLARE vDone BIT DEFAULT 0;
|
||||
DECLARE vCustomer MEDIUMINT;
|
||||
DECLARE vWarehouse TINYINT;
|
||||
DECLARE vCompany MEDIUMINT;
|
||||
DECLARE vAddress MEDIUMINT;
|
||||
DECLARE vRefundAgencyMode INT;
|
||||
DECLARE vItemFk INT;
|
||||
DECLARE vQuantity DECIMAL (10,2);
|
||||
DECLARE vConcept VARCHAR(50);
|
||||
DECLARE vPrice DECIMAL (10,2);
|
||||
DECLARE vDiscount TINYINT;
|
||||
DECLARE vSaleNew INT;
|
||||
DECLARE vSaleMain INT;
|
||||
DECLARE vZoneFk INT;
|
||||
DECLARE vDescription VARCHAR(50);
|
||||
DECLARE vTaxClassFk INT;
|
||||
DECLARE vTicketServiceTypeFk INT;
|
||||
|
||||
DECLARE cSales CURSOR FOR
|
||||
SELECT *
|
||||
FROM tmp.sale;
|
||||
|
||||
DECLARE cTicketServices CURSOR FOR
|
||||
SELECT *
|
||||
FROM tmp.ticketService;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = 1;
|
||||
|
||||
SELECT id INTO vRefundAgencyMode
|
||||
FROM agencyMode WHERE `name` = 'ABONO';
|
||||
|
||||
SELECT clientFk, warehouseFk, companyFk, addressFk
|
||||
INTO vCustomer, vWarehouse, vCompany, vAddress
|
||||
FROM ticket
|
||||
WHERE id = vOriginTicket;
|
||||
|
||||
SELECT id INTO vZoneFk
|
||||
FROM zone WHERE agencyModeFk = vRefundAgencyMode
|
||||
LIMIT 1;
|
||||
|
||||
INSERT INTO vn.ticket (
|
||||
clientFk,
|
||||
shipped,
|
||||
addressFk,
|
||||
agencyModeFk,
|
||||
nickname,
|
||||
warehouseFk,
|
||||
companyFk,
|
||||
landed,
|
||||
zoneFk
|
||||
)
|
||||
SELECT
|
||||
vCustomer,
|
||||
CURDATE(),
|
||||
vAddress,
|
||||
vRefundAgencyMode,
|
||||
a.nickname,
|
||||
vWarehouse,
|
||||
vCompany,
|
||||
CURDATE(),
|
||||
vZoneFk
|
||||
FROM address a
|
||||
WHERE a.id = vAddress;
|
||||
|
||||
SET vNewTicket = LAST_INSERT_ID();
|
||||
|
||||
SET vDone := 0;
|
||||
OPEN cSales;
|
||||
FETCH cSales INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount;
|
||||
|
||||
WHILE NOT vDone DO
|
||||
|
||||
INSERT INTO vn.sale(ticketFk, itemFk, quantity, concept, price, discount)
|
||||
VALUES( vNewTicket, vItemFk, vQuantity, vConcept, vPrice, vDiscount );
|
||||
|
||||
SET vSaleNew = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO vn.saleComponent(saleFk,componentFk,`value`)
|
||||
SELECT vSaleNew,componentFk,`value`
|
||||
FROM vn.saleComponent
|
||||
WHERE saleFk = vSaleMain;
|
||||
|
||||
FETCH cSales INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount;
|
||||
|
||||
END WHILE;
|
||||
CLOSE cSales;
|
||||
|
||||
SET vDone := 0;
|
||||
OPEN cTicketServices;
|
||||
FETCH cTicketServices INTO vDescription, vQuantity, vPrice, vTaxClassFk, vTicketServiceTypeFk;
|
||||
|
||||
WHILE NOT vDone DO
|
||||
|
||||
INSERT INTO vn.ticketService(description, quantity, price, taxClassFk, ticketFk, ticketServiceTypeFk)
|
||||
VALUES(vDescription, vQuantity, vPrice, vTaxClassFk, vNewTicket, vTicketServiceTypeFk);
|
||||
|
||||
FETCH cTicketServices INTO vDescription, vQuantity, vPrice, vTaxClassFk, vTicketServiceTypeFk;
|
||||
|
||||
END WHILE;
|
||||
CLOSE cTicketServices;
|
||||
|
||||
INSERT INTO vn.ticketRefund(refundTicketFk, originalTicketFk)
|
||||
VALUES(vNewTicket, vOriginTicket);
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE `vn`.`clientConfig` ADD `maxCreditRows` int(11) NULL COMMENT 'Máximo número de registros a mantener en la tabla clientCredit';
|
||||
|
||||
UPDATE `vn`.`clientConfig`
|
||||
SET `maxCreditRows` = 10
|
||||
WHERE `id` = 1;
|
|
@ -0,0 +1,8 @@
|
|||
ALTER TABLE `vn`.`propertyDms` DROP FOREIGN KEY propertyDms_FK;
|
||||
ALTER TABLE `vn`.`propertyDms` ADD CONSTRAINT propertyDms_FK FOREIGN KEY (dmsFk) REFERENCES `vn`.`dms`(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE `vn`.`clientDms` DROP FOREIGN KEY clientDms_ibfk_2;
|
||||
ALTER TABLE `vn`.`clientDms` ADD CONSTRAINT clientDms_ibfk_2 FOREIGN KEY (dmsFk) REFERENCES `vn`.`dms`(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE `vn`.`workerDocument` DROP FOREIGN KEY workerDocument_ibfk_2;
|
||||
ALTER TABLE `vn`.`workerDocument` ADD CONSTRAINT workerDocument_ibfk_2 FOREIGN KEY (document) REFERENCES `vn`.`dms`(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE `vn`.`dmsType` ADD monthToDelete INT UNSIGNED DEFAULT NULL NULL;
|
||||
ALTER TABLE `vn`.`dmsType` MODIFY COLUMN monthToDelete int(10) unsigned DEFAULT NULL NULL COMMENT 'Meses en el pasado para ir borrando registros, dejar a null para no borrarlos nunca';
|
||||
UPDATE `vn`.`dmsType`
|
||||
SET monthToDelete=6
|
||||
WHERE id=20;
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE TRIGGER `vn`.`dms_beforeDelete`
|
||||
BEFORE DELETE
|
||||
ON dms FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vCanNotBeDeleted INT;
|
||||
SELECT COUNT(*) INTO vCanNotBeDeleted
|
||||
FROM dmsType dt
|
||||
WHERE NOT (code <=> 'trash')
|
||||
AND dt.id = OLD.dmsTypeFk;
|
||||
|
||||
IF vCanNotBeDeleted THEN
|
||||
CALL util.throw('A dms can not be deleted');
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,175 @@
|
|||
DROP PROCEDURE IF EXISTS vn.clean;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`clean`()
|
||||
BEGIN
|
||||
DECLARE vDateShort DATETIME;
|
||||
DECLARE vOneYearAgo DATE;
|
||||
DECLARE vFourYearsAgo DATE;
|
||||
DECLARE v18Month DATE;
|
||||
DECLARE v26Month DATE;
|
||||
DECLARE v3Month DATE;
|
||||
DECLARE vTrashId varchar(15);
|
||||
|
||||
SET vDateShort = TIMESTAMPADD(MONTH, -2, CURDATE());
|
||||
SET vOneYearAgo = TIMESTAMPADD(YEAR,-1,CURDATE());
|
||||
SET vFourYearsAgo = TIMESTAMPADD(YEAR,-4,CURDATE());
|
||||
SET v18Month = TIMESTAMPADD(MONTH, -18,CURDATE());
|
||||
SET v26Month = TIMESTAMPADD(MONTH, -26,CURDATE());
|
||||
SET v3Month = TIMESTAMPADD(MONTH, -3, CURDATE());
|
||||
|
||||
DELETE FROM ticketParking WHERE created < vDateShort;
|
||||
DELETE FROM routesMonitor WHERE dated < vDateShort;
|
||||
DELETE FROM workerTimeControlLog WHERE created < vDateShort;
|
||||
DELETE FROM `message` WHERE sendDate < vDateShort;
|
||||
DELETE FROM messageInbox WHERE sendDate < vDateShort;
|
||||
DELETE FROM messageInbox WHERE sendDate < vDateShort;
|
||||
DELETE FROM workerTimeControl WHERE timed < vFourYearsAgo;
|
||||
DELETE FROM itemShelving WHERE created < CURDATE() AND visible = 0;
|
||||
DELETE FROM ticketDown WHERE created < TIMESTAMPADD(DAY,-1,CURDATE());
|
||||
DELETE FROM entryLog WHERE creationDate < vDateShort;
|
||||
DELETE IGNORE FROM expedition WHERE created < v26Month;
|
||||
DELETE FROM sms WHERE created < v18Month;
|
||||
DELETE FROM saleTracking WHERE created < vOneYearAgo;
|
||||
DELETE tobs FROM ticketObservation tobs
|
||||
JOIN ticket t ON tobs.ticketFk = t.id WHERE t.shipped < TIMESTAMPADD(YEAR,-2,CURDATE());
|
||||
DELETE sc.* FROM saleCloned sc JOIN sale s ON s.id = sc.saleClonedFk JOIN ticket t ON t.id = s.ticketFk WHERE t.shipped < vOneYearAgo;
|
||||
DELETE FROM sharingCart where ended < vDateShort;
|
||||
DELETE FROM sharingClient where ended < vDateShort;
|
||||
DELETE tw.* FROM ticketWeekly tw
|
||||
LEFT JOIN sale s ON s.ticketFk = tw.ticketFk WHERE s.itemFk IS NULL;
|
||||
DELETE FROM claim WHERE ticketCreated < vFourYearsAgo;
|
||||
DELETE FROM message WHERE sendDate < vDateShort;
|
||||
-- Robert ubicacion anterior de trevelLog comentario para debug
|
||||
DELETE sc FROM saleChecked sc
|
||||
JOIN sale s ON sc.saleFk = s.id WHERE s.created < vDateShort;
|
||||
DELETE FROM zoneEvent WHERE `type` = 'day' AND dated < v3Month;
|
||||
DELETE bm
|
||||
FROM buyMark bm
|
||||
JOIN buy b ON b.id = bm.id
|
||||
JOIN entry e ON e.id = b.entryFk
|
||||
JOIN travel t ON t.id = e.travelFk
|
||||
WHERE t.landed <= vDateShort;
|
||||
DELETE FROM stowaway WHERE created < v3Month;
|
||||
DELETE FROM vn.buy WHERE created < vDateShort AND entryFk = 9200;
|
||||
DELETE FROM vn.itemShelvingLog WHERE created < vDateShort;
|
||||
DELETE FROM vn.stockBuyed WHERE creationDate < vDateShort;
|
||||
|
||||
|
||||
-- Equipos duplicados
|
||||
DELETE w.*
|
||||
FROM workerTeam w
|
||||
JOIN (SELECT id, team, workerFk, COUNT(*) - 1 as duplicated
|
||||
FROM workerTeam
|
||||
GROUP BY team,workerFk
|
||||
HAVING duplicated
|
||||
) d ON d.team = w.team AND d.workerFk = w.workerFk AND d.id != w.id;
|
||||
|
||||
DELETE sc
|
||||
FROM saleComponent sc
|
||||
JOIN sale s ON s.id= sc.saleFk
|
||||
JOIN ticket t ON t.id= s.ticketFk
|
||||
WHERE t.shipped < v18Month;
|
||||
|
||||
DELETE c
|
||||
FROM vn.claim c
|
||||
JOIN vn.claimState cs ON cs.id = c.claimStateFk
|
||||
WHERE cs.description = "Anulado" AND
|
||||
c.created < vDateShort;
|
||||
DELETE
|
||||
FROM vn.expeditionTruck
|
||||
WHERE ETD < v3Month;
|
||||
|
||||
-- borrar travels sin entradas
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.thermographToDelete;
|
||||
CREATE TEMPORARY TABLE tmp.thermographToDelete
|
||||
SELECT th.id,th.dmsFk
|
||||
FROM vn.travel t
|
||||
LEFT JOIN vn.entry e ON e.travelFk = t.id
|
||||
JOIN vn.travelThermograph th ON th.travelFk = t.id
|
||||
WHERE t.shipped < TIMESTAMPADD(MONTH, -3, CURDATE()) AND e.travelFk IS NULL;
|
||||
|
||||
SELECT dt.id into vTrashId
|
||||
FROM vn.dmsType dt
|
||||
WHERE dt.code = 'trash';
|
||||
|
||||
UPDATE tmp.thermographToDelete th
|
||||
JOIN vn.dms d ON d.id = th.dmsFk
|
||||
SET d.dmsTypeFk = vTrashId;
|
||||
|
||||
DELETE th
|
||||
FROM tmp.thermographToDelete tmp
|
||||
JOIN vn.travelThermograph th ON th.id = tmp.id;
|
||||
|
||||
DELETE t
|
||||
FROM vn.travel t
|
||||
LEFT JOIN vn.entry e ON e.travelFk = t.id
|
||||
WHERE t.shipped < TIMESTAMPADD(MONTH, -3, CURDATE()) AND e.travelFk IS NULL;
|
||||
|
||||
UPDATE dms d
|
||||
JOIN dmsType dt ON dt.id = d.dmsTypeFk
|
||||
SET d.dmsTypeFk = vTrashId
|
||||
WHERE created < TIMESTAMPADD(MONTH, -dt.monthToDelete, CURDATE());
|
||||
|
||||
-- borrar entradas sin compras
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.entryToDelete;
|
||||
CREATE TEMPORARY TABLE tmp.entryToDelete
|
||||
SELECT e.*
|
||||
FROM vn.entry e
|
||||
LEFT JOIN vn.buy b ON b.entryFk = e.id
|
||||
JOIN vn.entryConfig ec ON e.id != ec.defaultEntry
|
||||
WHERE e.dated < TIMESTAMPADD(MONTH, -3, CURDATE()) AND b.entryFK IS NULL;
|
||||
|
||||
DELETE e
|
||||
FROM vn.entry e
|
||||
JOIN tmp.entryToDelete tmp ON tmp.id = e.id;
|
||||
|
||||
-- borrar de route registros menores a 4 años
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.routeToDelete;
|
||||
CREATE TEMPORARY TABLE tmp.routeToDelete
|
||||
SELECT *
|
||||
FROM vn.route r
|
||||
WHERE created < TIMESTAMPADD(YEAR,-4,CURDATE());
|
||||
|
||||
UPDATE tmp.routeToDelete tmp
|
||||
JOIN vn.dms d ON d.id = tmp.gestdocFk
|
||||
SET d.dmsTypeFk = vTrashId;
|
||||
|
||||
DELETE r
|
||||
FROM tmp.routeToDelete tmp
|
||||
JOIN vn.route r ON r.id = tmp.id;
|
||||
|
||||
-- borrar registros de dua y awb menores a 2 años
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.duaToDelete;
|
||||
CREATE TEMPORARY TABLE tmp.duaToDelete
|
||||
SELECT *
|
||||
FROM vn.dua
|
||||
WHERE operated < TIMESTAMPADD(YEAR,-2,CURDATE());
|
||||
|
||||
UPDATE tmp.duaToDelete tm
|
||||
JOIN vn.dms d ON d.id = tm.gestdocFk
|
||||
SET d.dmsTypeFk = vTrashId;
|
||||
|
||||
DELETE d
|
||||
FROM tmp.duaToDelete tmp
|
||||
JOIN vn.dua d ON d.id = tmp.id;
|
||||
|
||||
DELETE FROM vn.awb WHERE created < TIMESTAMPADD(YEAR,-2,CURDATE());
|
||||
|
||||
-- Borra los ficheros gestDoc
|
||||
INSERT INTO vn.printServerQueue(priorityFk, labelReportFk)VALUES(1,11);
|
||||
|
||||
-- Borra los registros de collection y ticketcollection
|
||||
DELETE FROM vn.collection WHERE created < vDateShort;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.thermographToDelete;
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.entryToDelete;
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.duaToDelete;
|
||||
|
||||
DELETE FROM travelLog WHERE creationDate < v3Month;
|
||||
|
||||
CALL shelving_clean;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES ('Dms','deleteTrashFiles','WRITE','ALLOW','ROLE','employee')
|
|
@ -1 +0,0 @@
|
|||
Delete file
|
|
@ -3,8 +3,8 @@ CREATE TABLE `vn`.`clientUnpaid` (
|
|||
`dated` date NOT NULL,
|
||||
`amount` double DEFAULT 0,
|
||||
PRIMARY KEY (`clientFk`),
|
||||
CONSTRAINT `clientUnpaid_clientFk` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE
|
||||
CONSTRAINT `clientUnpaid_clientFk` FOREIGN KEY (`clientFk`) REFERENCES `vn`.`client` (`id`) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('ClientUnpaid', '*', '*', 'ALLOW', 'ROLE', 'administrative');
|
||||
VALUES('ClientUnpaid', '*', '*', 'ALLOW', 'ROLE', 'administrative');
|
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE `vn`.`invoiceOut_queue` (
|
||||
`invoiceFk` int(10) unsigned not null,
|
||||
`queued` datetime default now() not null,
|
||||
`printed` datetime null,
|
||||
`status` VARCHAR(50) DEFAULT '' NULL,
|
||||
CONSTRAINT `invoiceOut_queue_pk` PRIMARY KEY (`invoiceFk`),
|
||||
CONSTRAINT `invoiceOut_queue_invoiceOut_id_fk` FOREIGN KEY (`invoiceFk`) REFERENCES `vn`.`invoiceOut` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
) comment 'Queue for PDF invoicing';
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE `vn`.`accountingType` ADD daysInFuture INT NULL;
|
||||
ALTER TABLE `vn`.`accountingType` MODIFY COLUMN daysInFuture int(11) DEFAULT 0 NULL;
|
|
@ -0,0 +1,4 @@
|
|||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES
|
||||
('ItemType', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||
('ItemType', '*', 'WRITE', 'ALLOW', 'ROLE', 'buyer');
|
|
@ -0,0 +1,14 @@
|
|||
CREATE TABLE `vn`.`mdbBranch` (
|
||||
`name` VARCHAR(255),
|
||||
PRIMARY KEY(`name`)
|
||||
);
|
||||
|
||||
CREATE TABLE `vn`.`mdbVersion` (
|
||||
`app` VARCHAR(255) NOT NULL,
|
||||
`branchFk` VARCHAR(255) NOT NULL,
|
||||
`version` INT,
|
||||
CONSTRAINT `mdbVersion_branchFk` FOREIGN KEY (`branchFk`) REFERENCES `vn`.`mdbBranch` (`name`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('MdbVersion', '*', '*', 'ALLOW', 'ROLE', 'developer');
|
|
@ -0,0 +1,13 @@
|
|||
CREATE TABLE `vn`.`chat` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`senderFk` int(10) unsigned DEFAULT NULL,
|
||||
`recipient` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`dated` date DEFAULT NULL,
|
||||
`checkUserStatus` tinyint(1) DEFAULT NULL,
|
||||
`message` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`status` tinyint(1) DEFAULT NULL,
|
||||
`attempts` int(1) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `chat_FK` (`senderFk`),
|
||||
CONSTRAINT `chat_FK` FOREIGN KEY (`senderFk`) REFERENCES `account`.`user` (`id`) ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
@ -0,0 +1,8 @@
|
|||
ALTER TABLE `vn`.`creditInsurance` ADD creditClassificationFk int(11) NULL;
|
||||
|
||||
UPDATE `vn`.`creditInsurance` AS `destiny`
|
||||
SET `destiny`.`creditClassificationFk`= (SELECT creditClassification FROM `vn`.`creditInsurance` AS `origin` WHERE `origin`.id = `destiny`.id);
|
||||
|
||||
ALTER TABLE `vn`.`creditInsurance`
|
||||
ADD CONSTRAINT `creditInsurance_creditClassificationFk` FOREIGN KEY (`creditClassificationFk`)
|
||||
REFERENCES `vn`.`creditClassification` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,3 @@
|
|||
INSERT INTO `salix`.`defaultViewConfig` (tableCode, columns)
|
||||
VALUES ('clientsDetail', '{"id":true,"phone":true,"city":true,"socialName":true,"salesPersonFk":true,"email":true,"name":false,"fi":false,"credit":false,"creditInsurance":false,"mobile":false,"street":false,"countryFk":false,"provinceFk":false,"postcode":false,"created":false,"businessTypeFk":false,"payMethodFk":false,"sageTaxTypeFk":false,"sageTransactionTypeFk":false,"isActive":false,"isVies":false,"isTaxDataChecked":false,"isEqualizated":false,"isFreezed":false,"hasToInvoice":false,"hasToInvoiceByAddress":false,"isToBeMailed":false,"hasLcr":false,"hasCoreVnl":false,"hasSepaVnl":false}');
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
DROP PROCEDURE IF EXISTS `vn`.`ticket_doRefund`;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_doRefund`(OUT vNewTicket INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Crea un ticket de abono a partir de tmp.sale y/o tmp.ticketService
|
||||
*
|
||||
* @return vNewTicket
|
||||
*/
|
||||
DECLARE vDone BIT DEFAULT 0;
|
||||
DECLARE vClientFk MEDIUMINT;
|
||||
DECLARE vWarehouse TINYINT;
|
||||
DECLARE vCompany MEDIUMINT;
|
||||
DECLARE vAddress MEDIUMINT;
|
||||
DECLARE vRefundAgencyMode INT;
|
||||
DECLARE vItemFk INT;
|
||||
DECLARE vQuantity DECIMAL (10,2);
|
||||
DECLARE vConcept VARCHAR(50);
|
||||
DECLARE vPrice DECIMAL (10,2);
|
||||
DECLARE vDiscount TINYINT;
|
||||
DECLARE vSaleNew INT;
|
||||
DECLARE vSaleMain INT;
|
||||
DECLARE vZoneFk INT;
|
||||
DECLARE vDescription VARCHAR(50);
|
||||
DECLARE vTaxClassFk INT;
|
||||
DECLARE vTicketServiceTypeFk INT;
|
||||
DECLARE vOriginTicket INT;
|
||||
|
||||
DECLARE cSales CURSOR FOR
|
||||
SELECT s.id, s.itemFk, - s.quantity, s.concept, s.price, s.discount
|
||||
FROM tmp.sale s;
|
||||
|
||||
DECLARE cTicketServices CURSOR FOR
|
||||
SELECT ts.description, - ts.quantity, ts.price, ts.taxClassFk, ts.ticketServiceTypeFk
|
||||
FROM tmp.ticketService ts;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||
|
||||
SELECT sub.ticketFk INTO vOriginTicket
|
||||
FROM (
|
||||
SELECT s.ticketFk
|
||||
FROM tmp.sale s
|
||||
UNION ALL
|
||||
SELECT ts.ticketFk
|
||||
FROM tmp.ticketService ts
|
||||
) sub
|
||||
LIMIT 1;
|
||||
|
||||
SELECT id INTO vRefundAgencyMode
|
||||
FROM agencyMode WHERE `name` = 'ABONO';
|
||||
|
||||
SELECT clientFk, warehouseFk, companyFk, addressFk
|
||||
INTO vClientFk, vWarehouse, vCompany, vAddress
|
||||
FROM ticket
|
||||
WHERE id = vOriginTicket;
|
||||
|
||||
SELECT id INTO vZoneFk
|
||||
FROM zone WHERE agencyModeFk = vRefundAgencyMode
|
||||
LIMIT 1;
|
||||
|
||||
INSERT INTO vn.ticket (
|
||||
clientFk,
|
||||
shipped,
|
||||
addressFk,
|
||||
agencyModeFk,
|
||||
nickname,
|
||||
warehouseFk,
|
||||
companyFk,
|
||||
landed,
|
||||
zoneFk
|
||||
)
|
||||
SELECT
|
||||
vClientFk,
|
||||
CURDATE(),
|
||||
vAddress,
|
||||
vRefundAgencyMode,
|
||||
a.nickname,
|
||||
vWarehouse,
|
||||
vCompany,
|
||||
CURDATE(),
|
||||
vZoneFk
|
||||
FROM address a
|
||||
WHERE a.id = vAddress;
|
||||
|
||||
SET vNewTicket = LAST_INSERT_ID();
|
||||
|
||||
SET vDone := FALSE;
|
||||
OPEN cSales;
|
||||
FETCH cSales INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount;
|
||||
|
||||
WHILE NOT vDone DO
|
||||
|
||||
INSERT INTO vn.sale(ticketFk, itemFk, quantity, concept, price, discount)
|
||||
VALUES( vNewTicket, vItemFk, vQuantity, vConcept, vPrice, vDiscount );
|
||||
|
||||
SET vSaleNew = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO vn.saleComponent(saleFk,componentFk,`value`)
|
||||
SELECT vSaleNew,componentFk,`value`
|
||||
FROM vn.saleComponent
|
||||
WHERE saleFk = vSaleMain;
|
||||
|
||||
FETCH cSales INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount;
|
||||
|
||||
END WHILE;
|
||||
CLOSE cSales;
|
||||
|
||||
SET vDone := FALSE;
|
||||
OPEN cTicketServices;
|
||||
FETCH cTicketServices INTO vDescription, vQuantity, vPrice, vTaxClassFk, vTicketServiceTypeFk;
|
||||
|
||||
WHILE NOT vDone DO
|
||||
|
||||
INSERT INTO vn.ticketService(description, quantity, price, taxClassFk, ticketFk, ticketServiceTypeFk)
|
||||
VALUES(vDescription, vQuantity, vPrice, vTaxClassFk, vNewTicket, vTicketServiceTypeFk);
|
||||
|
||||
FETCH cTicketServices INTO vDescription, vQuantity, vPrice, vTaxClassFk, vTicketServiceTypeFk;
|
||||
|
||||
END WHILE;
|
||||
CLOSE cTicketServices;
|
||||
|
||||
INSERT INTO vn.ticketRefund(refundTicketFk, originalTicketFk)
|
||||
VALUES(vNewTicket, vOriginTicket);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,11 @@
|
|||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`creditInsurance_beforeInsert`
|
||||
BEFORE INSERT ON `creditInsurance`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
IF NEW.creditClassificationFk THEN
|
||||
SET NEW.creditClassification = NEW.creditClassificationFk;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1 @@
|
|||
RENAME TABLE `edi`.`fileConfig` to `edi`.`tableConfig`;
|
|
@ -0,0 +1,22 @@
|
|||
CREATE TABLE `edi`.`fileConfig`
|
||||
(
|
||||
name varchar(25) NOT NULL,
|
||||
checksum text NULL,
|
||||
keyValue tinyint(1) default true NOT NULL,
|
||||
constraint fileConfig_pk
|
||||
primary key (name)
|
||||
);
|
||||
|
||||
create unique index fileConfig_name_uindex
|
||||
on `edi`.`fileConfig` (name);
|
||||
|
||||
|
||||
INSERT INTO `edi`.`fileConfig` (name, checksum, keyValue)
|
||||
VALUES ('FEC010104', null, 0);
|
||||
|
||||
INSERT INTO `edi`.`fileConfig` (name, checksum, keyValue)
|
||||
VALUES ('VBN020101', null, 1);
|
||||
|
||||
INSERT INTO `edi`.`fileConfig` (name, checksum, keyValue)
|
||||
VALUES ('florecompc2', null, 1);
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES
|
||||
('Client','setPassword','WRITE','ALLOW','ROLE','salesPerson'),
|
||||
('Client','updateUser','WRITE','ALLOW','ROLE','salesPerson');
|
|
@ -24,7 +24,10 @@ module.exports = class Docker {
|
|||
let d = new Date();
|
||||
let pad = v => v < 10 ? '0' + v : v;
|
||||
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
||||
|
||||
log('Building container image...');
|
||||
await this.execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./db`);
|
||||
log('Image built.');
|
||||
|
||||
let dockerArgs;
|
||||
|
||||
|
@ -39,6 +42,7 @@ module.exports = class Docker {
|
|||
|
||||
let runChown = process.platform != 'linux';
|
||||
|
||||
log('Starting container...');
|
||||
const container = await this.execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`);
|
||||
this.id = container.stdout.trim();
|
||||
|
||||
|
@ -158,6 +162,7 @@ module.exports = class Docker {
|
|||
return reject(new Error('Docker exited, please see the docker logs for more info'));
|
||||
|
||||
let conn = mysql.createConnection(myConf);
|
||||
|
||||
conn.on('error', () => {});
|
||||
conn.connect(err => {
|
||||
conn.destroy();
|
||||
|
|
1675
db/dump/fixtures.sql
1675
db/dump/fixtures.sql
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,43 @@
|
|||
CREATE SCHEMA IF NOT EXISTS `util`;
|
||||
USE `util`;
|
||||
|
||||
DELIMITER ;;
|
||||
DROP FUNCTION IF EXISTS `util`.`mockedDate`;
|
||||
CREATE FUNCTION `util`.`mockedDate`()
|
||||
RETURNS DATETIME
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
RETURN NOW();
|
||||
-- '2022-01-19 08:00:00'
|
||||
END ;;
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER ;;
|
||||
DROP FUNCTION IF EXISTS `util`.`VN_CURDATE`;
|
||||
CREATE FUNCTION `util`.`VN_CURDATE`()
|
||||
RETURNS DATE
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
RETURN DATE(mockedDate());
|
||||
END ;;
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER ;;
|
||||
DROP FUNCTION IF EXISTS `util`.`VN_CURTIME`;
|
||||
CREATE FUNCTION `util`.`VN_CURTIME`()
|
||||
RETURNS TIME
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
RETURN TIME(mockedDate());
|
||||
END ;;
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER ;;
|
||||
DROP FUNCTION IF EXISTS `util`.`VN_NOW`;
|
||||
CREATE FUNCTION `util`.`VN_NOW`()
|
||||
RETURNS DATETIME
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
RETURN mockedDate();
|
||||
END ;;
|
||||
DELIMITER ;
|
File diff suppressed because it is too large
Load Diff
|
@ -60,7 +60,6 @@ IGNORETABLES=(
|
|||
--ignore-table=vn.plantpassportAuthority__
|
||||
--ignore-table=vn.preparationException
|
||||
--ignore-table=vn.priceFixed__
|
||||
--ignore-table=vn.printer
|
||||
--ignore-table=vn.printingQueue
|
||||
--ignore-table=vn.printServerQueue__
|
||||
--ignore-table=vn.promissoryNote
|
||||
|
@ -97,5 +96,12 @@ mysqldump \
|
|||
--databases \
|
||||
${SCHEMAS[@]} \
|
||||
${IGNORETABLES[@]} \
|
||||
| sed 's/\bCURDATE\b/vn.VN_CURDATE/ig'\
|
||||
| sed 's/\bCURTIME\b/vn.VN_CURTIME/ig' \
|
||||
| sed 's/\bNOW\b/vn.VN_NOW/ig' \
|
||||
| sed 's/\bCURRENT_DATE\b/vn.VN_CURDATE/ig' \
|
||||
| sed 's/\bCURRENT_TIME\b/vn.VN_CURTIME/ig' \
|
||||
| sed 's/\bLOCALTIME\b/vn.VN_NOW/ig' \
|
||||
| sed 's/\bLOCALTIMESTAMP\b/vn.VN_NOW/ig' \
|
||||
| sed 's/ AUTO_INCREMENT=[0-9]* //g' \
|
||||
> dump/structure.sql
|
||||
> dump/structure.sql
|
|
@ -5,8 +5,9 @@ describe('zone zone_getLanded()', () => {
|
|||
it(`should return data for a shipped in the past`, async() => {
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmts.push('START TRANSACTION');
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
|
||||
let params = {
|
||||
addressFk: 121,
|
||||
|
@ -14,7 +15,8 @@ describe('zone zone_getLanded()', () => {
|
|||
warehouseFk: 1,
|
||||
showExpiredZones: true};
|
||||
|
||||
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(CURDATE(), INTERVAL -1 DAY), ?, ?, ?, ?)', [
|
||||
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(?, INTERVAL -1 DAY), ?, ?, ?, ?)', [
|
||||
date,
|
||||
params.addressFk,
|
||||
params.agencyModeFk,
|
||||
params.warehouseFk,
|
||||
|
@ -38,6 +40,8 @@ describe('zone zone_getLanded()', () => {
|
|||
it(`should return data for a shipped tomorrow`, async() => {
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
const date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
|
||||
stmts.push('START TRANSACTION');
|
||||
|
||||
|
@ -47,7 +51,8 @@ describe('zone zone_getLanded()', () => {
|
|||
warehouseFk: 1,
|
||||
showExpiredZones: false};
|
||||
|
||||
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(CURDATE(), INTERVAL +2 DAY), ?, ?, ?, ?)', [
|
||||
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(?, INTERVAL +2 DAY), ?, ?, ?, ?)', [
|
||||
date,
|
||||
params.addressFk,
|
||||
params.agencyModeFk,
|
||||
params.warehouseFk,
|
||||
|
|
|
@ -32,6 +32,7 @@ services:
|
|||
- /mnt/appdata/pdfs:/var/lib/salix/pdfs
|
||||
- /mnt/appdata/dms:/var/lib/salix/dms
|
||||
- /mnt/appdata/image:/var/lib/salix/image
|
||||
- /mnt/appdata/vn-access:/var/lib/salix/vn-access
|
||||
deploy:
|
||||
replicas: ${BACK_REPLICAS:?}
|
||||
placement:
|
||||
|
|
|
@ -55,6 +55,7 @@ export default {
|
|||
setPassword: '.vn-menu [name="setPassword"]',
|
||||
activateAccount: '.vn-menu [name="enableAccount"]',
|
||||
activateUser: '.vn-menu [name="activateUser"]',
|
||||
deactivateUser: '.vn-menu [name="deactivateUser"]',
|
||||
newPassword: 'vn-textfield[ng-model="$ctrl.newPassword"]',
|
||||
repeatPassword: 'vn-textfield[ng-model="$ctrl.repeatPassword"]',
|
||||
newRole: 'vn-autocomplete[ng-model="$ctrl.newRole"]',
|
||||
|
@ -101,6 +102,47 @@ export default {
|
|||
email: 'vn-user-mail-forwarding vn-textfield[ng-model="data.forwardTo"]',
|
||||
save: 'vn-user-mail-forwarding vn-submit'
|
||||
},
|
||||
accountAcl: {
|
||||
addAcl: 'vn-acl-index button vn-icon[icon="add"]',
|
||||
thirdAcl: 'vn-acl-index vn-list> a:nth-child(3)',
|
||||
deleteThirdAcl: 'vn-acl-index vn-list > a:nth-child(3) > vn-item-section > vn-icon-button[icon="delete"]',
|
||||
role: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.principalId"]',
|
||||
model: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.model"]',
|
||||
property: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.property"]',
|
||||
accessType: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.accessType"]',
|
||||
permission: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.permission"]',
|
||||
save: 'vn-acl-create vn-submit'
|
||||
},
|
||||
accountConnections: {
|
||||
firstConnection: 'vn-connections vn-list > a:nth-child(1)',
|
||||
deleteFirstConnection: 'vn-connections vn-list > a:nth-child(1) > vn-item-section > vn-icon-button[icon="exit_to_app"]'
|
||||
},
|
||||
accountAccounts: {
|
||||
syncRoles: 'vn-account-accounts vn-button[label="Synchronize roles"]',
|
||||
syncUser: 'vn-account-accounts vn-button[label="Synchronize user"]',
|
||||
syncAll: 'vn-account-accounts vn-button[label="Synchronize all"]',
|
||||
syncUserName: 'vn-textfield[ng-model="$ctrl.syncUser"]',
|
||||
syncUserPassword: 'vn-textfield[ng-model="$ctrl.syncPassword"]',
|
||||
buttonAccept: 'button[response="accept"]'
|
||||
},
|
||||
accountLdap: {
|
||||
checkEnable: 'vn-account-ldap vn-check[ng-model="watcher.hasData"]',
|
||||
server: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.server"]',
|
||||
rdn: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.rdn"]',
|
||||
password: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.password"]',
|
||||
userDn: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.userDn"]',
|
||||
groupDn: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.groupDn"]',
|
||||
save: 'vn-account-ldap vn-submit'
|
||||
},
|
||||
accountSamba: {
|
||||
checkEnable: 'vn-account-samba vn-check[ng-model="watcher.hasData"]',
|
||||
adDomain: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adDomain"]',
|
||||
adController: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adController"]',
|
||||
adUser: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adUser"]',
|
||||
adPassword: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adPassword"]',
|
||||
verifyCert: 'vn-account-samba vn-check[ng-model="$ctrl.config.verifyCert"]',
|
||||
save: 'vn-account-samba vn-submit'
|
||||
},
|
||||
clientsIndex: {
|
||||
createClientButton: `vn-float-button`
|
||||
},
|
||||
|
@ -982,8 +1024,8 @@ export default {
|
|||
save: 'vn-invoice-in-basic-data button[type=submit]'
|
||||
},
|
||||
invoiceInTax: {
|
||||
addTaxButton: 'vn-invoice-in-tax vn-icon-button[icon="add_circle"]',
|
||||
thirdExpence: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.expenseFk"]',
|
||||
addTaxButton: 'vn-invoice-in-tax vn-icon-button[vn-tooltip="Add tax"]',
|
||||
thirdExpense: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.expenseFk"]',
|
||||
thirdTaxableBase: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-input-number[ng-model="invoiceInTax.taxableBase"]',
|
||||
thirdTaxType: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.taxTypeSageFk"]',
|
||||
thirdTransactionType: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.transactionTypeSageFk"]',
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
require('@babel/register')({presets: ['@babel/env']});
|
||||
require('core-js/stable');
|
||||
require('regenerator-runtime/runtime');
|
||||
|
||||
const axios = require('axios');
|
||||
const Docker = require('../../db/docker.js');
|
||||
const e2eConfig = require('./config.js');
|
||||
const log = require('fancy-log');
|
||||
|
||||
process.on('warning', warning => {
|
||||
console.log(warning.name);
|
||||
console.log(warning.message);
|
||||
console.log(warning.stack);
|
||||
});
|
||||
|
||||
async function test() {
|
||||
if (process.argv[2] === 'show')
|
||||
process.env.E2E_SHOW = true;
|
||||
|
||||
const container = new Docker('salix-db');
|
||||
|
||||
await container.run();
|
||||
|
||||
const Jasmine = require('jasmine');
|
||||
const jasmine = new Jasmine();
|
||||
|
||||
const specFiles = [
|
||||
`./e2e/paths/01*/*[sS]pec.js`,
|
||||
`./e2e/paths/02*/*[sS]pec.js`,
|
||||
`./e2e/paths/03*/*[sS]pec.js`,
|
||||
`./e2e/paths/04*/*[sS]pec.js`,
|
||||
`./e2e/paths/05*/*[sS]pec.js`,
|
||||
`./e2e/paths/06*/*[sS]pec.js`,
|
||||
`./e2e/paths/07*/*[sS]pec.js`,
|
||||
`./e2e/paths/08*/*[sS]pec.js`,
|
||||
`./e2e/paths/09*/*[sS]pec.js`,
|
||||
`./e2e/paths/10*/*[sS]pec.js`,
|
||||
`./e2e/paths/11*/*[sS]pec.js`,
|
||||
`./e2e/paths/12*/*[sS]pec.js`,
|
||||
`./e2e/paths/13*/*[sS]pec.js`,
|
||||
`./e2e/paths/**/*[sS]pec.js`
|
||||
];
|
||||
|
||||
jasmine.loadConfig({
|
||||
spec_dir: '.',
|
||||
spec_files: specFiles,
|
||||
helpers: [],
|
||||
random: false,
|
||||
});
|
||||
|
||||
await backendStatus();
|
||||
|
||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
|
||||
await jasmine.execute();
|
||||
}
|
||||
|
||||
async function backendStatus() {
|
||||
log('Awaiting backend connection...');
|
||||
|
||||
const milliseconds = 1000;
|
||||
const maxAttempts = 10;
|
||||
|
||||
return new Promise(resolve => {
|
||||
let timer;
|
||||
let attempts = 1;
|
||||
timer = setInterval(async() => {
|
||||
try {
|
||||
attempts++;
|
||||
const url = `${e2eConfig.url}/api/Applications/status`;
|
||||
const {data} = await axios.get(url);
|
||||
|
||||
if (data == true) {
|
||||
clearInterval(timer);
|
||||
log('Backend connection stablished!');
|
||||
resolve(attempts);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error && attempts >= maxAttempts) {
|
||||
log('Could not connect to backend');
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
}, milliseconds);
|
||||
});
|
||||
}
|
||||
|
||||
test();
|
|
@ -8,7 +8,7 @@ describe('Client Edit web access path', () => {
|
|||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('employee', 'client');
|
||||
await page.accessToSearchResult('Bruce Banner');
|
||||
await page.accessToSearchResult('1105');
|
||||
await page.accessToSection('client.card.webAccess');
|
||||
});
|
||||
|
||||
|
@ -26,7 +26,7 @@ describe('Client Edit web access path', () => {
|
|||
|
||||
it(`should update the name`, async() => {
|
||||
await page.clearInput(selectors.clientWebAccess.userName);
|
||||
await page.write(selectors.clientWebAccess.userName, 'Hulk');
|
||||
await page.write(selectors.clientWebAccess.userName, 'Legion');
|
||||
await page.waitToClick(selectors.clientWebAccess.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
|
@ -43,30 +43,30 @@ describe('Client Edit web access path', () => {
|
|||
it('should confirm web access name have been updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.clientWebAccess.userName, 'value');
|
||||
|
||||
expect(result).toEqual('Hulk');
|
||||
expect(result).toEqual('Legion');
|
||||
});
|
||||
|
||||
it(`should navigate to the log section`, async() => {
|
||||
await page.accessToSection('client.card.log');
|
||||
});
|
||||
|
||||
it(`should confirm the last log is showing the updated client name and no modifications on the active checkbox`, async() => {
|
||||
it(`should confirm the last log shows the updated client name and no modifications on active checkbox`, async() => {
|
||||
let lastModificationPreviousValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.lastModificationPreviousValue, 'innerText');
|
||||
let lastModificationCurrentValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText');
|
||||
|
||||
expect(lastModificationPreviousValue).toEqual('name BruceBanner active false');
|
||||
expect(lastModificationCurrentValue).toEqual('name Hulk active false');
|
||||
expect(lastModificationPreviousValue).toEqual('name MaxEisenhardt active false');
|
||||
expect(lastModificationCurrentValue).toEqual('name Legion active false');
|
||||
});
|
||||
|
||||
it(`should confirm the penultimate log is showing the updated avtive field and no modifications on the client name`, async() => {
|
||||
it(`should confirm the penultimate log shows the updated active and no modifications on client name`, async() => {
|
||||
let penultimateModificationPreviousValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.penultimateModificationPreviousValue, 'innerText');
|
||||
let penultimateModificationCurrentValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.penultimateModificationCurrentValue, 'innerText');
|
||||
|
||||
expect(penultimateModificationPreviousValue).toEqual('name BruceBanner active true');
|
||||
expect(penultimateModificationCurrentValue).toEqual('name BruceBanner active false');
|
||||
expect(penultimateModificationPreviousValue).toEqual('name MaxEisenhardt active true');
|
||||
expect(penultimateModificationCurrentValue).toEqual('name MaxEisenhardt active false');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -123,19 +123,19 @@ describe('Client lock verified data path', () => {
|
|||
await page.accessToSection('client.card.fiscalData');
|
||||
}, 20000);
|
||||
|
||||
it('should confirm verified data button is disabled for salesAssistant', async() => {
|
||||
it('should confirm verified data button is enabled for salesAssistant', async() => {
|
||||
const isDisabled = await page.isDisabled(selectors.clientFiscalData.verifiedDataCheckbox);
|
||||
|
||||
expect(isDisabled).toBeTrue();
|
||||
expect(isDisabled).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return error when edit the social name', async() => {
|
||||
it('should now edit the social name', async() => {
|
||||
await page.clearInput(selectors.clientFiscalData.socialName);
|
||||
await page.write(selectors.clientFiscalData.socialName, 'new social name edition');
|
||||
await page.waitToClick(selectors.clientFiscalData.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain(`Not enough privileges to edit a client with verified data`);
|
||||
expect(message.text).toContain(`Data saved!`);
|
||||
});
|
||||
|
||||
it('should now confirm the social name have been edited once and for all', async() => {
|
||||
|
|
|
@ -28,12 +28,12 @@ describe('Client defaulter path', () => {
|
|||
const salesPersonName =
|
||||
await page.waitToGetProperty(selectors.clientDefaulter.firstSalesPersonName, 'innerText');
|
||||
|
||||
expect(clientName).toEqual('Ororo Munroe');
|
||||
expect(salesPersonName).toEqual('salesPersonNick');
|
||||
expect(clientName).toEqual('Bruce Banner');
|
||||
expect(salesPersonName).toEqual('developer');
|
||||
});
|
||||
|
||||
it('should first observation not changed', async() => {
|
||||
const expectedObservation = 'Madness, as you know, is like gravity, all it takes is a little push';
|
||||
const expectedObservation = 'Meeting with Black Widow 21st 9am';
|
||||
const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value');
|
||||
|
||||
expect(result).toContain(expectedObservation);
|
||||
|
|
|
@ -19,7 +19,7 @@ describe('InvoiceIn tax path', () => {
|
|||
|
||||
it('should add a new tax', async() => {
|
||||
await page.waitToClick(selectors.invoiceInTax.addTaxButton);
|
||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdExpence, '6210000567');
|
||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdExpense, '6210000567');
|
||||
await page.write(selectors.invoiceInTax.thirdTaxableBase, '100');
|
||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdTaxType, '6');
|
||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdTransactionType, 'Operaciones exentas');
|
||||
|
@ -37,9 +37,9 @@ describe('InvoiceIn tax path', () => {
|
|||
expect(result).toEqual('Taxable base €1,323.16');
|
||||
});
|
||||
|
||||
it('should navigate back to the tax section and check the reciently added line contains the expected expense', async() => {
|
||||
it('should navigate back to tax section, check the reciently added line contains the expected expense', async() => {
|
||||
await page.accessToSection('invoiceIn.card.tax');
|
||||
const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpence, 'value');
|
||||
const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpense, 'value');
|
||||
|
||||
expect(result).toEqual('6210000567: Alquiler VNH');
|
||||
});
|
||||
|
|
|
@ -36,8 +36,7 @@ describe('Account create and basic data path', () => {
|
|||
await page.waitForState('account.card.basicData');
|
||||
});
|
||||
|
||||
it('should reload the section and check the name is as expected', async() => {
|
||||
await page.reloadSection('account.card.basicData');
|
||||
it('should check the name is as expected', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.accountBasicData.name, 'value');
|
||||
|
||||
expect(result).toEqual('Remy');
|
||||
|
@ -103,25 +102,39 @@ describe('Account create and basic data path', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// creating the account without the active property set to true seems to be creating an active user anyways
|
||||
// describe('activate user', () => {
|
||||
// it(`should check the inactive user icon is present in the descriptor`, async() => {
|
||||
// await page.waitForSelector(selectors.accountDescriptor.activeUserIcon, {visible: true});
|
||||
// });
|
||||
describe('deactivate user', () => {
|
||||
it(`should check the inactive user icon isn't present in the descriptor just yet`, async() => {
|
||||
await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0);
|
||||
});
|
||||
|
||||
// it('should activate the user using the descriptor menu', async() => {
|
||||
// await page.waitToClick(selectors.accountDescriptor.menuButton);
|
||||
// await page.waitToClick(selectors.accountDescriptor.activateUser);
|
||||
// await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
||||
// const message = await page.waitForSnackbar();
|
||||
it('should deactivate the user using the descriptor menu', async() => {
|
||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
||||
await page.waitToClick(selectors.accountDescriptor.deactivateUser);
|
||||
await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
// expect(message.text).toContain('user enabled?');
|
||||
// });
|
||||
expect(message.text).toContain('User deactivated!');
|
||||
});
|
||||
|
||||
// it('should check the inactive user icon is not present anymore', async() => {
|
||||
// await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0);
|
||||
// });
|
||||
// });
|
||||
it('should check the inactive user icon is now present', async() => {
|
||||
await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('activate user', () => {
|
||||
it('should activate the user using the descriptor menu', async() => {
|
||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
||||
await page.waitToClick(selectors.accountDescriptor.activateUser);
|
||||
await page.waitToClick(selectors.accountDescriptor.acceptButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('User activated!');
|
||||
});
|
||||
|
||||
it('should check the inactive user icon is not present anymore', async() => {
|
||||
await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mail forwarding', () => {
|
||||
it('should activate the mail forwarding and set the recipent email', async() => {
|
||||
|
|
|
@ -56,7 +56,7 @@ describe('Account Alias create and basic data path', () => {
|
|||
expect(result).toContain('psykers');
|
||||
});
|
||||
|
||||
it('should search for the IT alias group then access to the users section then check the role listed is the expected one', async() => {
|
||||
it('should search IT alias then access the user section to check the role listed is the expected one', async() => {
|
||||
await page.accessToSearchResult('IT');
|
||||
await page.accessToSection('account.alias.card.users');
|
||||
const rolesCount = await page.countElement(selectors.accountAliasUsers.anyResult);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Account ACL path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('developer', 'account');
|
||||
await page.accessToSection('account.acl');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should go to create new acl', async() => {
|
||||
await page.waitToClick(selectors.accountAcl.addAcl);
|
||||
await page.waitForState('account.acl.create');
|
||||
});
|
||||
|
||||
it('should create new acl', async() => {
|
||||
await page.autocompleteSearch(selectors.accountAcl.role, 'sysadmin');
|
||||
await page.autocompleteSearch(selectors.accountAcl.model, 'UserAccount');
|
||||
await page.autocompleteSearch(selectors.accountAcl.accessType, '*');
|
||||
await page.autocompleteSearch(selectors.accountAcl.permission, 'ALLOW');
|
||||
await page.waitToClick(selectors.accountAcl.save);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Data saved!');
|
||||
});
|
||||
|
||||
it('should navigate to edit', async() => {
|
||||
await page.doSearch();
|
||||
await page.waitToClick(selectors.accountAcl.thirdAcl);
|
||||
await page.waitForState('account.acl.edit');
|
||||
});
|
||||
|
||||
it('should edit the third acl', async() => {
|
||||
await page.autocompleteSearch(selectors.accountAcl.model, 'Supplier');
|
||||
await page.autocompleteSearch(selectors.accountAcl.accessType, 'READ');
|
||||
await page.waitToClick(selectors.accountAcl.save);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Data saved!');
|
||||
});
|
||||
|
||||
it('should delete the third result', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.accountAcl.thirdAcl, 'innerText');
|
||||
await page.waitToClick(selectors.accountAcl.deleteThirdAcl);
|
||||
await page.waitToClick(selectors.globalItems.acceptButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
const newResult = await page.waitToGetProperty(selectors.accountAcl.thirdAcl, 'innerText');
|
||||
|
||||
expect(message.text).toContain('ACL removed');
|
||||
expect(result).not.toEqual(newResult);
|
||||
});
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue