merge(dev): refs #6366 merge dev
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Pablo Natek 2023-12-28 16:00:23 +01:00
commit f7ec64f3c1
224 changed files with 7589 additions and 4242 deletions

View File

@ -3,7 +3,7 @@
// Carácter predeterminado de final de línea. // Carácter predeterminado de final de línea.
"files.eol": "\n", "files.eol": "\n",
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": true "source.fixAll.eslint": "explicit"
}, },
"search.useIgnoreFiles": false, "search.useIgnoreFiles": false,
"editor.defaultFormatter": "dbaeumer.vscode-eslint", "editor.defaultFormatter": "dbaeumer.vscode-eslint",
@ -11,6 +11,9 @@
"[javascript]": { "[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint" "editor.defaultFormatter": "dbaeumer.vscode-eslint"
}, },
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"cSpell.words": [ "cSpell.words": [
"salix", "salix",
"fdescribe" "fdescribe"

View File

@ -5,12 +5,35 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2348.01] - 2023-11-30 ## [2402.01] - 2024-01-11
### Added ### Added
### Changed ### Changed
### Fixed ### Fixed
## [2400.01] - 2024-01-04
### Added
### Changed
### Fixed
## [2350.01] - 2023-12-14
### Características Añadidas 🆕
- **Tickets → Expediciones:** Añadido soporte para Viaexpress
## [2348.01] - 2023-11-30
### Características Añadidas 🆕
- **Tickets → Adelantar:** Permite mover lineas sin generar negativos
- **Tickets → Adelantar:** Permite modificar la fecha de los tickets
- **Trabajadores → Notificaciones:** Nueva sección (lilium)
### Correcciones 🛠️
- **Tickets → RocketChat:** Arreglada detección de cambios
## [2346.01] - 2023-11-16 ## [2346.01] - 2023-11-16
### Added ### Added

View File

@ -1,4 +1,4 @@
FROM debian:bullseye-slim FROM debian:bookworm-slim
ENV TZ Europe/Madrid ENV TZ Europe/Madrid
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
@ -25,7 +25,13 @@ RUN apt-get update \
libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 \ libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 \
libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 \ libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 \
libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \ libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget \ fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
# Extra dependencies
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
samba-common-bin samba-dsdb-modules\
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/* \
&& npm -g install pm2 && npm -g install pm2

View File

@ -8,7 +8,7 @@ Salix is also the scientific name of a beautifull tree! :)
Required applications. Required applications.
* Node.js >= 16.x LTS * Node.js
* Docker * Docker
* Git * Git
@ -17,20 +17,7 @@ You will need to install globally the following items.
$ sudo npm install -g jest gulp-cli $ sudo npm install -g jest gulp-cli
``` ```
For the usage of jest --watch on macOs. ## Installing dependencies and launching
```
$ brew install watchman
```
* [watchman](https://facebook.github.io/watchman/)
## Linux Only Prerequisites
Your user must be on the docker group to use it so you will need to run this command:
```
$ sudo usermod -a -G docker yourusername
```
## Getting Started // Installing
Pull from repository. Pull from repository.
@ -76,29 +63,6 @@ In Visual Studio Code we use the ESLint extension.
ext install dbaeumer.vscode-eslint ext install dbaeumer.vscode-eslint
``` ```
Gitlens for visualization of code authorship
```
ext install eamodio.gitlens
```
Spanish language pack
```
ext install ms-ceintl.vscode-language-pack-es
```
### Recommended extensions
Material icon Theme
```
ext install pkief.material-icon-theme
```
Material UI Themes
```
ext install equinusocio.vsc-material-theme
```
## Built With ## Built With
* [angularjs](https://angularjs.org/) * [angularjs](https://angularjs.org/)

View File

@ -49,7 +49,7 @@ module.exports = Self => {
ish.packing, ish.packing,
ish.grouping, ish.grouping,
s.isAdded, s.isAdded,
s.originalQuantity, s.originalQuantity,
s.quantity saleQuantity, s.quantity saleQuantity,
iss.quantity reservedQuantity, iss.quantity reservedQuantity,
SUM(iss.quantity) OVER (PARTITION BY s.id ORDER BY ish.id) accumulatedQuantity, SUM(iss.quantity) OVER (PARTITION BY s.id ORDER BY ish.id) accumulatedQuantity,
@ -75,7 +75,7 @@ module.exports = Self => {
LEFT JOIN itemColor ic ON ic.itemFk = s.itemFk LEFT JOIN itemColor ic ON ic.itemFk = s.itemFk
LEFT JOIN origin o ON o.id = i.originFk LEFT JOIN origin o ON o.id = i.originFk
WHERE tc.collectionFk = ? WHERE tc.collectionFk = ?
GROUP BY ish.id, p.code, p2.code GROUP BY s.id, ish.id, p.code, p2.code
ORDER BY pickingOrder;`, [id], myOptions); ORDER BY pickingOrder;`, [id], myOptions);
if (print) if (print)
@ -105,7 +105,7 @@ module.exports = Self => {
LEFT JOIN vn.buy c ON c.itemFk = s.itemFk LEFT JOIN vn.buy c ON c.itemFk = s.itemFk
LEFT JOIN vn.entry e ON e.id = c.entryFk LEFT JOIN vn.entry e ON e.id = c.entryFk
LEFT JOIN vn.travel tr ON tr.id = e.travelFk LEFT JOIN vn.travel tr ON tr.id = e.travelFk
WHERE s.ticketFk = ? WHERE s.ticketFk = ?
AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`, AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`,
[ticketId], myOptions); [ticketId], myOptions);
ticket.sales = []; ticket.sales = [];

View File

@ -1,133 +0,0 @@
module.exports = Self => {
Self.remoteMethodCtx('newCollection', {
description: 'Make a new collection of tickets',
accessType: 'WRITE',
accepts: [{
arg: 'collectionFk',
type: 'Number',
required: false,
description: 'The collection id'
}, {
arg: 'sectorFk',
type: 'Number',
required: true,
description: 'The sector of worker'
}, {
arg: 'vWagons',
type: 'Number',
required: true,
description: 'The number of wagons'
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/newCollection`,
verb: 'POST'
}
});
Self.newCollection = async(ctx, collectionFk, sectorFk, vWagons) => {
let query = '';
const userId = ctx.req.accessToken.userId;
if (!collectionFk) {
query = `CALL vn.collectionTrain_newBeta(?,?,?)`;
const [result] = await Self.rawSql(query, [sectorFk, vWagons, userId], {userId});
if (result.length == 0)
throw new Error(`No collections for today`);
collectionFk = result[0].vCollectionFk;
}
query = `CALL vn.collectionTicket_get(?)`;
const [tickets] = await Self.rawSql(query, [collectionFk], {userId});
query = `CALL vn.collectionSale_get(?)`;
const [sales] = await Self.rawSql(query, [collectionFk], {userId});
query = `CALL vn.collectionPlacement_get(?)`;
const [placements] = await Self.rawSql(query, [collectionFk], {userId});
query = `CALL vn.collectionSticker_print(?,?)`;
await Self.rawSql(query, [collectionFk, sectorFk], {userId});
return makeCollection(tickets, sales, placements, collectionFk);
};
/**
* Returns a collection json
* @param {*} tickets - Request tickets
* @param {*} sales - Request sales
* @param {*} placements - Request placements
* @param {*} collectionFk - Request placements
* @return {Object} Collection JSON
*/
async function makeCollection(tickets, sales, placements, collectionFk) {
let collection = [];
for (let i = 0; i < tickets.length; i++) {
let ticket = {};
ticket['ticketFk'] = tickets[i]['ticketFk'];
ticket['level'] = tickets[i]['level'];
ticket['agencyName'] = tickets[i]['agencyName'];
ticket['warehouseFk'] = tickets[i]['warehouseFk'];
ticket['salesPersonFk'] = tickets[i]['salesPersonFk'];
let ticketSales = [];
for (let x = 0; x < sales.length; x++) {
if (sales[x]['ticketFk'] == ticket['ticketFk']) {
let sale = {};
sale['collectionFk'] = collectionFk;
sale['ticketFk'] = sales[x]['ticketFk'];
sale['saleFk'] = sales[x]['saleFk'];
sale['itemFk'] = sales[x]['itemFk'];
sale['quantity'] = sales[x]['quantity'];
if (sales[x]['quantityPicked'] != null)
sale['quantityPicked'] = sales[x]['quantityPicked'];
else
sale['quantityPicked'] = 0;
sale['longName'] = sales[x]['longName'];
sale['size'] = sales[x]['size'];
sale['color'] = sales[x]['color'];
sale['discount'] = sales[x]['discount'];
sale['price'] = sales[x]['price'];
sale['stems'] = sales[x]['stems'];
sale['category'] = sales[x]['category'];
sale['origin'] = sales[x]['origin'];
sale['clientFk'] = sales[x]['clientFk'];
sale['productor'] = sales[x]['productor'];
sale['reserved'] = sales[x]['reserved'];
sale['isPreviousPrepared'] = sales[x]['isPreviousPrepared'];
sale['isPrepared'] = sales[x]['isPrepared'];
sale['isControlled'] = sales[x]['isControlled'];
let salePlacements = [];
for (let z = 0; z < placements.length; z++) {
if (placements[z]['saleFk'] == sale['saleFk']) {
let placement = {};
placement['saleFk'] = placements[z]['saleFk'];
placement['itemFk'] = placements[z]['itemFk'];
placement['placement'] = placements[z]['placement'];
placement['shelving'] = placements[z]['shelving'];
placement['created'] = placements[z]['created'];
placement['visible'] = placements[z]['visible'];
placement['order'] = placements[z]['order'];
placement['grouping'] = placements[z]['grouping'];
salePlacements.push(placement);
}
}
sale['placements'] = salePlacements;
ticketSales.push(sale);
}
}
ticket['sales'] = ticketSales;
collection.push(ticket);
}
return collection;
}
};

View File

@ -1,12 +0,0 @@
const {models} = require('vn-loopback/server/server');
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 models.Collection.newCollection(ctx, 1, 1, 1);
expect(response.length).toBeGreaterThan(0);
expect(response[0].ticketFk).toEqual(2);
});
});

View File

@ -22,8 +22,8 @@ module.exports = Self => {
Self.removeFile = async(ctx, id, options) => { Self.removeFile = async(ctx, id, options) => {
const models = Self.app.models; const models = Self.app.models;
let tx;
const myOptions = {}; const myOptions = {};
let tx;
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);

View File

@ -24,15 +24,40 @@ describe('docuware upload()', () => {
}); });
it('should try upload file', async() => { it('should try upload file', async() => {
const tx = await models.Docuware.beginTransaction({});
spyOn(ticketModel, 'deliveryNotePdf').and.returnValue(new Promise(resolve => resolve({}))); spyOn(ticketModel, 'deliveryNotePdf').and.returnValue(new Promise(resolve => resolve({})));
let error; let error;
try { try {
await models.Docuware.upload(ctx, ticketIds, fileCabinetName); const options = {transaction: tx};
const user = await models.UserConfig.findById(userId, null, options);
await user.updateAttribute('tabletFk', 'Tablet1');
await models.Docuware.upload(ctx, ticketIds, fileCabinetName, options);
await tx.rollback();
} catch (e) { } catch (e) {
error = e.message; error = e;
await tx.rollback();
} }
expect(error).toEqual('Action not allowed on the test environment'); expect(error.message).toEqual('Action not allowed on the test environment');
});
it('should throw error when not have tablet assigned', async() => {
const tx = await models.Docuware.beginTransaction({});
spyOn(ticketModel, 'deliveryNotePdf').and.returnValue(new Promise(resolve => resolve({})));
let error;
try {
const options = {transaction: tx};
await models.Docuware.upload(ctx, ticketIds, fileCabinetName, options);
await tx.rollback();
} catch (e) {
error = e;
await tx.rollback();
}
expect(error.message).toEqual('This user does not have an assigned tablet');
}); });
}); });

View File

@ -29,12 +29,24 @@ module.exports = Self => {
} }
}); });
Self.upload = async function(ctx, ticketIds, fileCabinet) { Self.upload = async function(ctx, ticketIds, fileCabinet, options) {
delete ctx.args.ticketIds; delete ctx.args.ticketIds;
const models = Self.app.models; const models = Self.app.models;
const action = 'store'; const action = 'store';
const options = await Self.getOptions(); const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const userConfig = await models.UserConfig.findById(ctx.req.accessToken.userId, {
fields: ['tabletFk']
}, myOptions);
if (!userConfig?.tabletFk)
throw new UserError('This user does not have an assigned tablet');
const docuwareOptions = await Self.getOptions();
const fileCabinetId = await Self.getFileCabinet(fileCabinet); const fileCabinetId = await Self.getFileCabinet(fileCabinet);
const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId); const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId);
@ -45,7 +57,7 @@ module.exports = Self => {
const deliveryNote = await models.Ticket.deliveryNotePdf(ctx, { const deliveryNote = await models.Ticket.deliveryNotePdf(ctx, {
id, id,
type: 'deliveryNote' type: 'deliveryNote'
}); }, myOptions);
// get ticket data // get ticket data
const ticket = await models.Ticket.findById(id, { const ticket = await models.Ticket.findById(id, {
include: [{ include: [{
@ -54,7 +66,7 @@ module.exports = Self => {
fields: ['id', 'name', 'fi'] fields: ['id', 'name', 'fi']
} }
}] }]
}); }, myOptions);
// upload file // upload file
const templateJson = { const templateJson = {
@ -102,7 +114,7 @@ module.exports = Self => {
{ {
'FieldName': 'FILTRO_TABLET', 'FieldName': 'FILTRO_TABLET',
'ItemElementName': 'string', 'ItemElementName': 'string',
'Item': 'Tablet1', 'Item': userConfig.tabletFk,
} }
] ]
}; };
@ -116,11 +128,11 @@ module.exports = Self => {
const deleteJson = { const deleteJson = {
'Field': [{'FieldName': 'ESTADO', 'Item': 'Pendiente eliminar', 'ItemElementName': 'String'}] 'Field': [{'FieldName': 'ESTADO', 'Item': 'Pendiente eliminar', 'ItemElementName': 'String'}]
}; };
const deleteUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/Fields`; const deleteUri = `${docuwareOptions.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/Fields`;
await axios.put(deleteUri, deleteJson, options.headers); await axios.put(deleteUri, deleteJson, docuwareOptions.headers);
} }
const uploadUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents?StoreDialogId=${dialogId}`; const uploadUri = `${docuwareOptions.url}/FileCabinets/${fileCabinetId}/Documents?StoreDialogId=${dialogId}`;
const FormData = require('form-data'); const FormData = require('form-data');
const data = new FormData(); const data = new FormData();
@ -130,7 +142,7 @@ module.exports = Self => {
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data',
'X-File-ModifiedDate': Date.vnNew(), 'X-File-ModifiedDate': Date.vnNew(),
'Cookie': options.headers.headers.Cookie, 'Cookie': docuwareOptions.headers.headers.Cookie,
...data.getHeaders() ...data.getHeaders()
}, },
}; };
@ -141,11 +153,11 @@ module.exports = Self => {
const $t = ctx.req.__; const $t = ctx.req.__;
const message = $t('Failed to upload delivery note', {id}); const message = $t('Failed to upload delivery note', {id});
if (uploaded.length) if (uploaded.length)
await models.TicketTracking.setDelivered(ctx, uploaded); await models.TicketTracking.setDelivered(ctx, uploaded, myOptions);
throw new UserError(message); throw new UserError(message);
} }
uploaded.push(id); uploaded.push(id);
} }
return models.TicketTracking.setDelivered(ctx, ticketIds); return models.TicketTracking.setDelivered(ctx, ticketIds, myOptions);
}; };
}; };

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<DeleteEnvio xmlns="http://82.223.6.71:82">
<IdCliente><%= viaexpressConfig.client %></IdCliente>
<Usuario><%= viaexpressConfig.user %></Usuario>
<Password><%= viaexpressConfig.password %></Password>
<etiqueta><%= externalId %></etiqueta>
</DeleteEnvio>
</soap12:Body>
</soap12:Envelope>

View File

@ -0,0 +1,45 @@
const axios = require('axios');
const {DOMParser} = require('xmldom');
module.exports = Self => {
Self.remoteMethod('deleteExpedition', {
description: 'Delete a shipment by providing the expedition ID, interacting with Viaexpress API',
accessType: 'WRITE',
accepts: [{
arg: 'expeditionFk',
type: 'number',
required: true
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/deleteExpedition`,
verb: 'POST'
}
});
Self.deleteExpedition = async expeditionFk => {
const models = Self.app.models;
const viaexpressConfig = await models.ViaexpressConfig.findOne({
fields: ['url']
});
const renderedXml = await models.ViaexpressConfig.deleteExpeditionRenderer(expeditionFk);
const response = await axios.post(`${viaexpressConfig.url}ServicioVxClientes.asmx`, renderedXml, {
headers: {
'Content-Type': 'application/soap+xml; charset=utf-8'
}
});
const xmlString = response.data;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
const resultElement = xmlDoc.getElementsByTagName('DeleteEnvioResult')[0];
const result = resultElement.textContent;
return result;
};
};

View File

@ -0,0 +1,44 @@
const fs = require('fs');
const ejs = require('ejs');
module.exports = Self => {
Self.remoteMethod('deleteExpeditionRenderer', {
description: 'Renders the data from an XML',
accessType: 'READ',
accepts: [{
arg: 'expeditionFk',
type: 'number',
required: true
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/deleteExpeditionRenderer`,
verb: 'GET'
}
});
Self.deleteExpeditionRenderer = async expeditionFk => {
const models = Self.app.models;
const viaexpressConfig = await models.ViaexpressConfig.findOne({
fields: ['client', 'user', 'password']
});
const expedition = await models.Expedition.findOne({
fields: ['id', 'externalId'],
where: {id: expeditionFk}
});
const data = {
viaexpressConfig,
externalId: expedition.externalId
};
const template = fs.readFileSync(__dirname + '/deleteExpedition.ejs', 'utf-8');
const renderedXml = ejs.render(template, data);
return renderedXml;
};
};

View File

@ -1,5 +1,14 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
const {models} = require('vn-loopback/server/server');
const handlePromiseLogout = (Self, {id}, courtesyTime) => {
new Promise(res => {
setTimeout(() => {
res(Self.logout(id));
}
, courtesyTime * 1000);
});
};
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('renewToken', { Self.remoteMethodCtx('renewToken', {
description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it', description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it',
@ -16,23 +25,32 @@ module.exports = Self => {
}); });
Self.renewToken = async function(ctx) { Self.renewToken = async function(ctx) {
const models = Self.app.models; const {accessToken: token} = ctx.req;
const token = ctx.req.accessToken;
const now = new Date(); // Check if current token is valid
const differenceMilliseconds = now - token.created; const isValid = await validateToken(token);
const differenceSeconds = Math.floor(differenceMilliseconds / 1000); if (isValid)
return token;
const fields = ['renewPeriod', 'courtesyTime']; const {courtesyTime} = await models.AccessTokenConfig.findOne({fields: ['courtesyTime']});
const accessTokenConfig = await models.AccessTokenConfig.findOne({fields});
if (differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime) // Schedule to remove current token
throw new UserError(`The renew period has not been exceeded`, 'periodNotExceeded'); handlePromiseLogout(Self, token, courtesyTime);
await Self.logout(token.id); // Create new accessToken
const user = await Self.findById(token.userId); const user = await Self.findById(token.userId);
const accessToken = await user.createAccessToken(); const accessToken = await user.createAccessToken();
return {id: accessToken.id, ttl: accessToken.ttl}; return {id: accessToken.id, ttl: accessToken.ttl};
}; };
async function validateToken(token) {
const accessTokenConfig = await models.AccessTokenConfig.findOne({fields: ['renewPeriod', 'courtesyTime']});
const now = Date.now();
const differenceMilliseconds = now - token.created;
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
const isValid = differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime;
return isValid;
}
}; };

View File

@ -49,8 +49,7 @@ module.exports = Self => {
if (vnUser.twoFactor) if (vnUser.twoFactor)
throw new ForbiddenError(null, 'REQUIRES_2FA'); throw new ForbiddenError(null, 'REQUIRES_2FA');
} }
return Self.validateLogin(user, password, ctx);
return Self.validateLogin(user, password);
}; };
Self.passExpired = async vnUser => { Self.passExpired = async vnUser => {

View File

@ -0,0 +1,51 @@
const {models} = require('vn-loopback/server/server');
describe('Renew Token', () => {
const startingTime = Date.now();
let ctx = null;
beforeAll(async() => {
const unAuthCtx = {
req: {
headers: {},
connection: {
remoteAddress: '127.0.0.1'
},
getLocale: () => 'en'
},
args: {}
};
let login = await models.VnUser.signIn(unAuthCtx, 'salesAssistant', 'nightmare');
let accessToken = await models.AccessToken.findById(login.token);
ctx = {req: {accessToken: accessToken}};
});
beforeEach(() => {
jasmine.clock().install();
jasmine.clock().mockDate(new Date(startingTime));
});
afterEach(() => {
jasmine.clock().uninstall();
});
it('should renew token', async() => {
const mockDate = new Date(startingTime + 26600000);
jasmine.clock().mockDate(mockDate);
console.log(startingTime, mockDate)
const {id} = await models.VnUser.renewToken(ctx);
expect(id).not.toEqual(ctx.req.accessToken.id);
});
it('NOT should renew', async() => {
let error;
let response;
try {
response = await models.VnUser.renewToken(ctx);
} catch (e) {
error = e;
}
expect(error).toBeUndefined();
expect(response.id).toEqual(ctx.req.accessToken.id);
});
});

View File

@ -2,7 +2,7 @@ const {models} = require('vn-loopback/server/server');
describe('VnUser Sign-in()', () => { describe('VnUser Sign-in()', () => {
const employeeId = 1; const employeeId = 1;
const unauthCtx = { const unAuthCtx = {
req: { req: {
headers: {}, headers: {},
connection: { connection: {
@ -12,10 +12,21 @@ describe('VnUser Sign-in()', () => {
}, },
args: {} args: {}
}; };
const {VnUser, AccessToken} = models; const {VnUser, AccessToken, SignInLog} = models;
describe('when credentials are correct', () => { describe('when credentials are correct', () => {
it('should return the token if user uses email', async() => {
let login = await VnUser.signIn(unAuthCtx, 'salesAssistant@mydomain.com', 'nightmare');
let accessToken = await AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}};
let signInLog = await SignInLog.find({where: {token: accessToken.id}});
expect(signInLog.length).toEqual(0);
await VnUser.logout(ctx.req.accessToken.id);
});
it('should return the token', async() => { it('should return the token', async() => {
let login = await VnUser.signIn(unauthCtx, 'salesAssistant', 'nightmare'); let login = await VnUser.signIn(unAuthCtx, 'salesAssistant', 'nightmare');
let accessToken = await AccessToken.findById(login.token); let accessToken = await AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}}; let ctx = {req: {accessToken: accessToken}};
@ -25,7 +36,7 @@ describe('VnUser Sign-in()', () => {
}); });
it('should return the token if the user doesnt exist but the client does', async() => { it('should return the token if the user doesnt exist but the client does', async() => {
let login = await VnUser.signIn(unauthCtx, 'PetterParker', 'nightmare'); let login = await VnUser.signIn(unAuthCtx, 'PetterParker', 'nightmare');
let accessToken = await AccessToken.findById(login.token); let accessToken = await AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}}; let ctx = {req: {accessToken: accessToken}};
@ -40,7 +51,7 @@ describe('VnUser Sign-in()', () => {
let error; let error;
try { try {
await VnUser.signIn(unauthCtx, 'IDontExist', 'TotallyWrongPassword'); await VnUser.signIn(unAuthCtx, 'IDontExist', 'TotallyWrongPassword');
} catch (e) { } catch (e) {
error = e; error = e;
} }
@ -61,7 +72,7 @@ describe('VnUser Sign-in()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
await employee.updateAttribute('twoFactor', 'email', options); await employee.updateAttribute('twoFactor', 'email', options);
await VnUser.signIn(unauthCtx, 'employee', 'nightmare', options); await VnUser.signIn(unAuthCtx, 'employee', 'nightmare', options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
@ -86,7 +97,7 @@ describe('VnUser Sign-in()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
await employee.updateAttribute('passExpired', yesterday, options); await employee.updateAttribute('passExpired', yesterday, options);
await VnUser.signIn(unauthCtx, 'employee', 'nightmare', options); await VnUser.signIn(unAuthCtx, 'employee', 'nightmare', options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();

View File

@ -1,17 +0,0 @@
module.exports = Self => {
Self.remoteMethod('validateToken', {
description: 'Validates the current logged user token',
returns: {
type: 'Boolean',
root: true
},
http: {
path: `/validateToken`,
verb: 'GET'
}
});
Self.validateToken = async function() {
return true;
};
};

View File

@ -1,6 +1,5 @@
module.exports = Self => { module.exports = Self => {
require('../methods/collection/getCollection')(Self); require('../methods/collection/getCollection')(Self);
require('../methods/collection/newCollection')(Self);
require('../methods/collection/getSectors')(Self); require('../methods/collection/getSectors')(Self);
require('../methods/collection/setSaleQuantity')(Self); require('../methods/collection/setSaleQuantity')(Self);
require('../methods/collection/previousLabel')(Self); require('../methods/collection/previousLabel')(Self);

View File

@ -0,0 +1,17 @@
{
"name": "docuwareTablet",
"base": "VnModel",
"options": {
"mysql": {
"table": "docuwareTablet"
}
},
"properties": {
"tablet": {
"type": "string"
},
"description": {
"type": "string"
}
}
}

View File

@ -26,6 +26,9 @@
}, },
"darkMode": { "darkMode": {
"type": "boolean" "type": "boolean"
},
"tabletFk": {
"type": "string"
} }
}, },
"relations": { "relations": {
@ -43,6 +46,11 @@
"type": "belongsTo", "type": "belongsTo",
"model": "VnUser", "model": "VnUser",
"foreignKey": "userFk" "foreignKey": "userFk"
} },
"Tablet": {
"type": "belongsTo",
"model": "docuwareTablet",
"foreignKey": "tabletFk"
}
} }
} }

View File

@ -1,4 +1,6 @@
module.exports = Self => { module.exports = Self => {
require('../methods/viaexpress-config/internationalExpedition')(Self); require('../methods/viaexpress-config/internationalExpedition')(Self);
require('../methods/viaexpress-config/renderer')(Self); require('../methods/viaexpress-config/renderer')(Self);
require('../methods/viaexpress-config/deleteExpedition')(Self);
require('../methods/viaexpress-config/deleteExpeditionRenderer')(Self);
}; };

View File

@ -2,6 +2,7 @@ const vnModel = require('vn-loopback/common/models/vn-model');
const {Email} = require('vn-print'); const {Email} = require('vn-print');
const ForbiddenError = require('vn-loopback/util/forbiddenError'); const ForbiddenError = require('vn-loopback/util/forbiddenError');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
const UserError = require('vn-loopback/util/user-error');
module.exports = function(Self) { module.exports = function(Self) {
vnModel(Self); vnModel(Self);
@ -9,7 +10,6 @@ module.exports = function(Self) {
require('../methods/vn-user/sign-in')(Self); require('../methods/vn-user/sign-in')(Self);
require('../methods/vn-user/acl')(Self); require('../methods/vn-user/acl')(Self);
require('../methods/vn-user/recover-password')(Self); require('../methods/vn-user/recover-password')(Self);
require('../methods/vn-user/validate-token')(Self);
require('../methods/vn-user/privileges')(Self); require('../methods/vn-user/privileges')(Self);
require('../methods/vn-user/validate-auth')(Self); require('../methods/vn-user/validate-auth')(Self);
require('../methods/vn-user/renew-token')(Self); require('../methods/vn-user/renew-token')(Self);
@ -92,7 +92,11 @@ module.exports = function(Self) {
}; };
Self.on('resetPasswordRequest', async function(info) { Self.on('resetPasswordRequest', async function(info) {
const url = await Self.app.models.Url.getUrl(); const loopBackContext = LoopBackContext.getCurrentContext();
const httpCtx = {req: loopBackContext.active};
const httpRequest = httpCtx.req.http.req;
const headers = httpRequest.headers;
const origin = headers.origin;
const defaultHash = '/reset-password?access_token=$token$'; const defaultHash = '/reset-password?access_token=$token$';
const recoverHashes = { const recoverHashes = {
@ -108,7 +112,7 @@ module.exports = function(Self) {
const params = { const params = {
recipient: info.email, recipient: info.email,
lang: user.lang, lang: user.lang,
url: url.slice(0, -1) + recoverHash url: origin + '/#!' + recoverHash
}; };
const options = Object.assign({}, info.options); const options = Object.assign({}, info.options);
@ -120,11 +124,43 @@ module.exports = function(Self) {
return email.send(); return email.send();
}); });
Self.validateLogin = async function(user, password) { /**
let loginInfo = Object.assign({password}, Self.userUses(user)); * Sign-in validate
token = await Self.login(loginInfo, 'user'); * @param {String} user The user
* @param {Object} userToken Options
* @param {Object} token accessToken
* @param {Object} ctx context
*/
Self.signInValidate = async(user, userToken, token, ctx) => {
const [[key, value]] = Object.entries(Self.userUses(user));
const isOwner = Self.rawSql(`SELECT ? = ? `, [userToken[key], value]);
if (!isOwner) {
await Self.app.models.SignInLog.create({
userName: user,
token: token.id,
userFk: userToken.id,
ip: ctx.req.ip,
owner: isOwner
});
throw new UserError('Try again');
}
};
/**
* Validate login params
* @param {String} user The user
* @param {String} password
* @param {Object} ctx context
*/
Self.validateLogin = async function(user, password, ctx) {
const loginInfo = Object.assign({password}, Self.userUses(user));
const token = await Self.login(loginInfo, 'user');
const userToken = await token.user.get(); const userToken = await token.user.get();
if (ctx)
await Self.signInValidate(user, userToken, token, ctx);
try { try {
await Self.app.models.Account.sync(userToken.name, password); await Self.app.models.Account.sync(userToken.name, password);
} catch (err) { } catch (err) {
@ -173,8 +209,8 @@ module.exports = function(Self) {
}; };
Self.sharedClass._methods.find(method => method.name == 'changePassword').ctor.settings.acls = Self.sharedClass._methods.find(method => method.name == 'changePassword').ctor.settings.acls =
Self.sharedClass._methods.find(method => method.name == 'changePassword').ctor.settings.acls Self.sharedClass._methods.find(method => method.name == 'changePassword').ctor.settings.acls
.filter(acl => acl.property != 'changePassword'); .filter(acl => acl.property != 'changePassword');
Self.userSecurity = async(ctx, userId, options) => { Self.userSecurity = async(ctx, userId, options) => {
const models = Self.app.models; const models = Self.app.models;
@ -212,16 +248,21 @@ module.exports = function(Self) {
const env = process.env.NODE_ENV; const env = process.env.NODE_ENV;
const liliumUrl = await Self.app.models.Url.findOne({ const liliumUrl = await Self.app.models.Url.findOne({
where: {and: [ where: {
{appName: 'lilium'}, and: [
{environment: env} {appName: 'lilium'},
]} {environment: env}
]
}
}); });
class Mailer { class Mailer {
async send(verifyOptions, cb) { async send(verifyOptions, cb) {
const url = new URL(verifyOptions.verifyHref);
if (process.env.NODE_ENV) url.port = '';
const params = { const params = {
url: verifyOptions.verifyHref, url: url.href,
recipient: verifyOptions.to recipient: verifyOptions.to
}; };

View File

@ -104,13 +104,6 @@
"permission": "ALLOW" "permission": "ALLOW"
}, },
{ {
"property": "validateToken",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"property": "validateAuth", "property": "validateAuth",
"accessType": "EXECUTE", "accessType": "EXECUTE",
"principalType": "ROLE", "principalType": "ROLE",

View File

@ -7,6 +7,10 @@ process.on('warning', warning => {
console.log(warning.stack); console.log(warning.stack);
}); });
process.on('SIGUSR2', async() => {
if (container) await container.rm();
});
process.on('exit', async function() { process.on('exit', async function() {
if (container) await container.rm(); if (container) await container.rm();
}); });

View File

@ -74,7 +74,7 @@ BEGIN
clientFk, clientFk,
dued, dued,
companyFk, companyFk,
cplusInvoiceType477Fk siiTypeInvoiceOutFk
) )
SELECT SELECT
1, 1,
@ -118,13 +118,13 @@ BEGIN
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef) SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
FROM tmp.ticketToInvoice ti; FROM tmp.ticketToInvoice ti;
CALL invoiceExpenceMake(vNewInvoiceId); CALL invoiceExpenseMake(vNewInvoiceId);
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea); CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
UPDATE invoiceOut io UPDATE invoiceOut io
JOIN ( JOIN (
SELECT SUM(amount) AS total SELECT SUM(amount) AS total
FROM invoiceOutExpence FROM invoiceOutExpense
WHERE invoiceOutFk = vNewInvoiceId WHERE invoiceOutFk = vNewInvoiceId
) base ) base
JOIN ( JOIN (
@ -166,18 +166,18 @@ BEGIN
SET @vTaxableBaseServices := 0.00; SET @vTaxableBaseServices := 0.00;
SET @vTaxCodeGeneral := NULL; SET @vTaxCodeGeneral := NULL;
INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInId, @vTaxableBaseServices, sub.expenceFk, sub.taxTypeSageFk , sub.transactionTypeSageFk SELECT vNewInvoiceInId, @vTaxableBaseServices, sub.expenseFk, sub.taxTypeSageFk , sub.transactionTypeSageFk
FROM ( FROM (
SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, i.expenceFk, i.taxTypeSageFk , i.transactionTypeSageFk, @vTaxCodeGeneral := i.taxClassCodeFk SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, i.expenseFk, i.taxTypeSageFk , i.transactionTypeSageFk, @vTaxCodeGeneral := i.taxClassCodeFk
FROM tmp.ticketServiceTax tst FROM tmp.ticketServiceTax tst
JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code
WHERE i.isService WHERE i.isService
HAVING taxableBase HAVING taxableBase
) sub; ) sub;
INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInId, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, @vTaxableBaseServices, 0) taxableBase, i.expenceFk, i.taxTypeSageFk , i.transactionTypeSageFk SELECT vNewInvoiceInId, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, @vTaxableBaseServices, 0) taxableBase, i.expenseFk, i.taxTypeSageFk , i.transactionTypeSageFk
FROM tmp.ticketTax tt FROM tmp.ticketTax tt
JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code
WHERE !i.isService WHERE !i.isService

View File

@ -96,7 +96,7 @@ BEGIN
clientFk, clientFk,
dued, dued,
companyFk, companyFk,
cplusInvoiceType477Fk siiTypeInvoiceOutFk
) )
SELECT SELECT
1, 1,
@ -139,13 +139,13 @@ BEGIN
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef) SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
FROM tmp.ticketToInvoice ti; FROM tmp.ticketToInvoice ti;
CALL invoiceExpenceMake(vNewInvoiceId); CALL invoiceExpenseMake(vNewInvoiceId);
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea); CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
UPDATE invoiceOut io UPDATE invoiceOut io
JOIN ( JOIN (
SELECT SUM(amount) total SELECT SUM(amount) total
FROM invoiceOutExpence FROM invoiceOutExpense
WHERE invoiceOutFk = vNewInvoiceId WHERE invoiceOutFk = vNewInvoiceId
) base ) base
JOIN ( JOIN (
@ -182,15 +182,15 @@ BEGIN
SET @vTaxableBaseServices := 0.00; SET @vTaxableBaseServices := 0.00;
SET @vTaxCodeGeneral := NULL; SET @vTaxCodeGeneral := NULL;
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInFk, SELECT vNewInvoiceInFk,
@vTaxableBaseServices, @vTaxableBaseServices,
sub.expenceFk, sub.expenseFk,
sub.taxTypeSageFk, sub.taxTypeSageFk,
sub.transactionTypeSageFk sub.transactionTypeSageFk
FROM ( FROM (
SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase,
i.expenceFk, i.expenseFk,
i.taxTypeSageFk, i.taxTypeSageFk,
i.transactionTypeSageFk, i.transactionTypeSageFk,
@vTaxCodeGeneral := i.taxClassCodeFk @vTaxCodeGeneral := i.taxClassCodeFk
@ -200,11 +200,11 @@ BEGIN
HAVING taxableBase HAVING taxableBase
) sub; ) sub;
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInFk, SELECT vNewInvoiceInFk,
SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral,
@vTaxableBaseServices, 0) taxableBase, @vTaxableBaseServices, 0) taxableBase,
i.expenceFk, i.expenseFk,
i.taxTypeSageFk , i.taxTypeSageFk ,
i.transactionTypeSageFk i.transactionTypeSageFk
FROM tmp.ticketTax tt FROM tmp.ticketTax tt

View File

@ -96,7 +96,7 @@ BEGIN
clientFk, clientFk,
dued, dued,
companyFk, companyFk,
cplusInvoiceType477Fk siiTypeInvoiceOutFk
) )
SELECT SELECT
1, 1,
@ -135,13 +135,13 @@ BEGIN
INSERT INTO ticketTracking(stateFk,ticketFk,workerFk) INSERT INTO ticketTracking(stateFk,ticketFk,workerFk)
SELECT * FROM tmp.updateInter; SELECT * FROM tmp.updateInter;
CALL invoiceExpenceMake(vNewInvoiceId); CALL invoiceExpenseMake(vNewInvoiceId);
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea); CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
UPDATE invoiceOut io UPDATE invoiceOut io
JOIN ( JOIN (
SELECT SUM(amount) total SELECT SUM(amount) total
FROM invoiceOutExpence FROM invoiceOutExpense
WHERE invoiceOutFk = vNewInvoiceId WHERE invoiceOutFk = vNewInvoiceId
) base ) base
JOIN ( JOIN (
@ -178,15 +178,15 @@ BEGIN
SET @vTaxableBaseServices := 0.00; SET @vTaxableBaseServices := 0.00;
SET @vTaxCodeGeneral := NULL; SET @vTaxCodeGeneral := NULL;
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInFk, SELECT vNewInvoiceInFk,
@vTaxableBaseServices, @vTaxableBaseServices,
sub.expenceFk, sub.expenseFk,
sub.taxTypeSageFk, sub.taxTypeSageFk,
sub.transactionTypeSageFk sub.transactionTypeSageFk
FROM ( FROM (
SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase,
i.expenceFk, i.expenseFk,
i.taxTypeSageFk, i.taxTypeSageFk,
i.transactionTypeSageFk, i.transactionTypeSageFk,
@vTaxCodeGeneral := i.taxClassCodeFk @vTaxCodeGeneral := i.taxClassCodeFk
@ -196,11 +196,11 @@ BEGIN
HAVING taxableBase HAVING taxableBase
) sub; ) sub;
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInFk, SELECT vNewInvoiceInFk,
SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral,
@vTaxableBaseServices, 0) taxableBase, @vTaxableBaseServices, 0) taxableBase,
i.expenceFk, i.expenseFk,
i.taxTypeSageFk , i.taxTypeSageFk ,
i.transactionTypeSageFk i.transactionTypeSageFk
FROM tmp.ticketTax tt FROM tmp.ticketTax tt

View File

@ -1,6 +1,6 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES VALUES
('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), ('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('CplusInvoiceType477', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), ('SiiTypeInvoiceOut', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), ('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative'); ('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative');

View File

@ -0,0 +1,4 @@
-- Auto-generated SQL script #202311061003
UPDATE salix.accessTokenConfig
SET courtesyTime=60
WHERE id=1;

View File

@ -0,0 +1 @@
CALL `account`.`role_sync`();

View File

@ -0,0 +1,2 @@
ALTER TABLE account.sambaConfig
ADD userDn varchar(255) NOT NULL COMMENT 'Base DN for users without domain DN part';

View File

@ -0,0 +1,152 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canAdvance`(vDateFuture DATE, vDateToAdvance DATE, vWarehouseFk INT)
BEGIN
/**
* Devuelve los tickets y la cantidad de lineas de venta que se pueden adelantar.
*
* @param vDateFuture Fecha de los tickets que se quieren adelantar.
* @param vDateToAdvance Fecha a cuando se quiere adelantar.
* @param vWarehouseFk Almacén
*/
DECLARE vDateInventory DATE;
SELECT inventoried INTO vDateInventory FROM config;
CREATE OR REPLACE TEMPORARY TABLE tmp.stock
(itemFk INT PRIMARY KEY,
amount INT)
ENGINE = MEMORY;
INSERT INTO tmp.stock(itemFk, amount)
SELECT itemFk, SUM(quantity) amount FROM
(
SELECT itemFk, quantity
FROM itemTicketOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryIn
WHERE landed >= vDateInventory
AND landed <= vDateToAdvance
AND isVirtualStock = FALSE
AND warehouseInFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseOutFk = vWarehouseFk
) t
GROUP BY itemFk HAVING amount != 0;
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
(INDEX (id))
SELECT
origin.ticketFk futureId,
dest.ticketFk id,
dest.state,
origin.futureState,
origin.futureIpt,
dest.ipt,
origin.workerFk,
origin.futureLiters,
origin.futureLines,
dest.shipped,
origin.shipped futureShipped,
dest.totalWithVat,
origin.totalWithVat futureTotalWithVat,
dest.agency,
dest.agencyModeFk,
origin.futureAgency,
origin.agencyModeFk futureAgencyModeFk,
dest.lines,
dest.liters,
origin.futureLines - origin.hasStock AS notMovableLines,
(origin.futureLines = origin.hasStock) AS isFullMovable,
dest.zoneFk,
origin.futureZoneFk,
origin.futureZoneName,
origin.classColor futureClassColor,
dest.classColor,
origin.clientFk futureClientFk,
origin.addressFk futureAddressFk,
origin.warehouseFk futureWarehouseFk,
origin.companyFk futureCompanyFk,
IFNULL(dest.nickname, origin.nickname) nickname,
dest.landed
FROM (
SELECT
s.ticketFk,
c.salesPersonFk workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
am.name futureAgency,
count(s.id) futureLines,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters,
SUM((s.quantity <= IFNULL(st.amount,0))) hasStock,
z.id futureZoneFk,
z.name futureZoneName,
st.classColor,
t.clientFk,
t.nickname,
t.addressFk,
t.warehouseFk,
t.companyFk,
t.agencyModeFk
FROM ticket t
JOIN client c ON c.id = t.clientFk
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
JOIN zone z ON t.zoneFk = z.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN tmp.stock st ON st.itemFk = i.id
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
) origin
LEFT JOIN (
SELECT
t.id ticketFk,
st.name state,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt,
t.shipped,
t.totalWithVat,
am.name agency,
CAST(SUM(litros) AS DECIMAL(10,0)) liters,
CAST(COUNT(*) AS DECIMAL(10,0)) `lines`,
st.classColor,
t.clientFk,
t.nickname,
t.addressFk,
t.zoneFk,
t.warehouseFk,
t.companyFk,
t.landed,
t.agencyModeFk
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
WHERE t.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance)
AND t.warehouseFk = vWarehouseFk
AND st.order <= 5
GROUP BY t.id
) dest ON dest.addressFk = origin.addressFk
WHERE origin.hasStock;
DROP TEMPORARY TABLE tmp.stock;
END$$
DELIMITER ;

View File

@ -0,0 +1,21 @@
--
-- Table structure for table `signInLog`
-- Description: log to debug cross-login error
--
DROP TABLE IF EXISTS `account`.`signInLog`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `account`.`signInLog` (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`token` varchar(255) NOT NULL ,
`userFk` int(10) unsigned DEFAULT NULL,
`creationDate` timestamp NULL DEFAULT current_timestamp(),
`userName` varchar(30) NOT NULL,
`ip` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
`owner` tinyint(1) DEFAULT 1,
KEY `userFk` (`userFk`),
CONSTRAINT `signInLog_ibfk_1` FOREIGN KEY (`userFk`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);

View File

View File

@ -0,0 +1,26 @@
DELETE FROM `salix`.`ACL`
WHERE
model = 'Route'
AND property = '*'
AND accessType = 'READ';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Route', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'getRoutesByWorker', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'canViewAllRoute', 'READ', 'ALLOW', 'ROLE', 'deliveryBoss'),
('Route', 'cmr', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'downloadCmrsZip', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'downloadZip', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'filter', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'getByWorker', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'getDeliveryPoint', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'getExternalCmrs', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'getSuggestedTickets', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'getTickets', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Route', 'guessPriority', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Route', 'insertTicket', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Route', 'getDeliveryPoint', 'READ', 'ALLOW', 'ROLE', 'deliveryBoss'),
('Route', 'summary', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,46 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`delivery_beforeInsert`
BEFORE INSERT ON `delivery`
FOR EACH ROW
BEGIN
IF (NEW.longitude IS NOT NULL AND NEW.latitude IS NOT NULL AND NEW.ticketFK IS NOT NULL)
THEN
UPDATE address
SET longitude = NEW.longitude,
latitude = NEW.latitude
WHERE id IN (
SELECT addressFK
FROM ticket
WHERE id = NEW.ticketFk
);
END IF;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`delivery_beforeUpdate`
BEFORE UPDATE ON `delivery`
FOR EACH ROW
BEGIN
IF (NEW.longitude IS NOT NULL AND NEW.latitude IS NOT NULL AND NEW.ticketFK IS NOT NULL)
THEN
UPDATE address
SET longitude = NEW.longitude,
latitude = NEW.latitude
WHERE id IN (
SELECT addressFK
FROM ticket
WHERE id = NEW.ticketFk
);
END IF;
END$$
DELIMITER ;
ALTER TABLE `vn`.`address` MODIFY COLUMN longitude decimal(11,7) DEFAULT NULL NULL COMMENT 'Indica la última longitud proporcionada por tabla delivery';
ALTER TABLE `vn`.`address` MODIFY COLUMN latitude decimal(11,7) DEFAULT NULL NULL COMMENT 'Indica la última latitud proporcionada por tabla delivery';

View File

@ -0,0 +1 @@
ALTER TABLE `vn`.`ticketTracking` CHANGE `workerFk` `userFk` int(10) unsigned DEFAULT NULL NULL;

View File

@ -0,0 +1,4 @@
RENAME TABLE `vn`.`clientCreditLimit` TO `vn`.`roleCreditLimit`;
ALTER TABLE `vn`.`roleCreditLimit` DROP FOREIGN KEY `clientCreditLimit_FK`;
ALTER TABLE `vn`.`roleCreditLimit` ADD CONSTRAINT `roleCreditLimit_FK` FOREIGN KEY (`roleFk`) REFERENCES `account`.`role`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1 @@
DELETE FROM `account`.`signInLog` where owner <> FALSE

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
CREATE SCHEMA IF NOT EXISTS `vn2008`;
USE `vn`;
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `ticketState`
AS SELECT `tt`.`created` AS `updated`,
`tt`.`stateFk` AS `stateFk`,
`tt`.`userFk` AS `workerFk`,
`tls`.`ticketFk` AS `ticketFk`,
`s`.`id` AS `state`,
`s`.`order` AS `productionOrder`,
`s`.`alertLevel` AS `alertLevel`,
`s`.`code` AS `code`,
`tls`.`ticketFk` AS `ticket`,
`tt`.`userFk` AS `worker`,
`s`.`isPreviousPreparable` AS `isPreviousPreparable`,
`s`.`isPicked` AS `isPicked`
FROM (
(
`ticketLastState` `tls`
JOIN `ticketTracking` `tt` ON(`tt`.`id` = `tls`.`ticketTrackingFk`)
)
JOIN `state` `s` ON(`s`.`id` = `tt`.`stateFk`)
);
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn2008`.`v_inter`
AS SELECT `tt`.`id` AS `inter_id`,
`tt`.`stateFk` AS `state_id`,
`tt`.`notes` AS `nota`,
`tt`.`created` AS `odbc_date`,
`tt`.`ticketFk` AS `Id_Ticket`,
`tt`.`userFk` AS `Id_Trabajador`,
`tt`.`supervisorFk` AS `Id_supervisor`
FROM `vn`.`ticketTracking` `tt`;
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `ticketStateToday`
AS SELECT
`ts`.`ticket` AS `ticket`,
`ts`.`state` AS `state`,
`ts`.`productionOrder` AS `productionOrder`,
`ts`.`alertLevel` AS `alertLevel`,
`ts`.`worker` AS `worker`,
`ts`.`code` AS `code`,
`ts`.`updated` AS `updated`,
`ts`.`isPicked` AS `isPicked`
FROM
(`ticketState` `ts`
JOIN `ticket` `t` ON
(`t`.`id` = `ts`.`ticket`))
WHERE
`t`.`shipped` BETWEEN `util`.`VN_CURDATE`() AND `MIDNIGHT`(`util`.`VN_CURDATE`());

View File

View File

@ -0,0 +1,10 @@
-- vn.docuwareTablet definition
CREATE TABLE `vn`.`docuwareTablet` (
`tablet` varchar(100) NOT NULL PRIMARY KEY,
`description` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
ALTER TABLE `vn`.`userConfig`
ADD COLUMN tabletFk varchar(100) DEFAULT NULL,
ADD FOREIGN KEY (tabletFk) REFERENCES `vn`.`docuwareTablet`(tablet);

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,7 @@
CREATE ROLE 'salix';
GRANT 'salix' TO 'root'@'%';
SET DEFAULT ROLE 'salix' FOR 'root'@'%';
CREATE SCHEMA IF NOT EXISTS `vn2008`; CREATE SCHEMA IF NOT EXISTS `vn2008`;
CREATE SCHEMA IF NOT EXISTS `tmp`; CREATE SCHEMA IF NOT EXISTS `tmp`;
@ -59,10 +63,6 @@ INSERT IGNORE INTO `vn`.`greugeConfig`(`id`, `freightPickUpPrice`)
VALUES VALUES
('1', '11'); ('1', '11');
INSERT INTO `vn`.`packagingConfig`(`upperGap`)
VALUES
('10');
UPDATE `account`.`role` SET id = 100 WHERE id = 0; UPDATE `account`.`role` SET id = 100 WHERE id = 0;
INSERT INTO `account`.`roleConfig`(`id`, `mysqlPassword`, `rolePrefix`, `userPrefix`, `userHost`, `tplUser`) INSERT INTO `account`.`roleConfig`(`id`, `mysqlPassword`, `rolePrefix`, `userPrefix`, `userHost`, `tplUser`)
@ -73,7 +73,7 @@ CALL `account`.`role_sync`;
INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `role`,`active`,`email`, `lang`, `image`, `password`) INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `role`,`active`,`email`, `lang`, `image`, `password`)
SELECT id, name, CONCAT(name, 'Nick'), id, 1, CONCAT(name, '@mydomain.com'), 'en', '4fa3ada0-3ac4-11eb-9ab8-27f6fc3b85fd', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2' SELECT id, name, CONCAT(name, 'Nick'), id, 1, CONCAT(name, '@mydomain.com'), 'en', '4fa3ada0-3ac4-11eb-9ab8-27f6fc3b85fd', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2'
FROM `account`.`role` WHERE id <> 20 FROM `account`.`role`
ORDER BY id; ORDER BY id;
INSERT INTO `account`.`account`(`id`) INSERT INTO `account`.`account`(`id`)
@ -87,9 +87,15 @@ INSERT INTO `vn`.`educationLevel` (`id`, `name`)
(1, 'ESTUDIOS PRIMARIOS COMPLETOS'), (1, 'ESTUDIOS PRIMARIOS COMPLETOS'),
(2, 'ENSEÑANZAS DE BACHILLERATO'); (2, 'ENSEÑANZAS DE BACHILLERATO');
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `bossFk`)
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, NULL
FROM `account`.`user`
WHERE `id` = 9;
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `bossFk`) INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `bossFk`)
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, 9 SELECT id,UPPER(LPAD(role, 3, '0')), name, name, 9
FROM `account`.`user`; FROM `account`.`user`
WHERE `id` <> 9;
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20; UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
UPDATE `vn`.`worker` SET bossFk = 20 WHERE id = 1 OR id = 9; UPDATE `vn`.`worker` SET bossFk = 20 WHERE id = 1 OR id = 9;
@ -360,18 +366,18 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`)
INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`,`clientTypeFk`, `hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`, `businessTypeFk`,`typeFk`) INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`,`clientTypeFk`, `hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`, `businessTypeFk`,`typeFk`)
VALUES VALUES
(1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','loses'), (1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','normal'),
(1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','normal'), (1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','normal'),
(1103, 'Clark Kent', '06815934E', 'SUPER MAN', 'lois lane', '344 CLINTON STREET, APARTAMENT 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','normal'), (1103, 'Clark Kent', '06815934E', 'SUPER MAN', 'lois lane', '344 CLINTON STREET, APARTAMENT 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','normal'),
(1104, 'Tony Stark', '06089160W', 'IRON MAN', 'Pepper Potts', '10880 MALIBU POINT, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','normal'), (1104, 'Tony Stark', '06089160W', 'IRON MAN', 'Pepper Potts', '10880 MALIBU POINT, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist','normal'),
(1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist','normal'), (1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist','normal'),
(1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'), (1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'),
(1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'), (1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'),
(1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1, 'florist','normal'), (1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1, 'florist','normal'),
(1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist','normal'), (1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist','normal'),
(1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist','normal'), (1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist','normal'),
(1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others','normal'), (1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others','loses'),
(1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others','normal'); (1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others','loses');
INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`) INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`)
SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, util.VN_CURDATE(), 1 SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, util.VN_CURDATE(), 1
@ -405,7 +411,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1), (5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1),
(6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1), (6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1),
(7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1), (7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1),
(8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1), (8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1),
(9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1), (9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1),
(10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1), (10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1),
(11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1), (11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1),
@ -437,7 +443,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0), (125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0),
(126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0), (126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0),
(127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0), (127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0),
(128, 'Cerebro', 'address 28', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0), (128, 'Cerebro', 'address 28', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0),
(129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0), (129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0),
(130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0); (130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0);
@ -487,7 +493,7 @@ INSERT INTO `vn`.`clientCredit`(`clientFk`, `workerFk`, `amount`, `created`)
(1104, 9, 90 , util.VN_CURDATE()), (1104, 9, 90 , util.VN_CURDATE()),
(1105, 9, 90 , util.VN_CURDATE()); (1105, 9, 90 , util.VN_CURDATE());
INSERT INTO `vn`.`clientCreditLimit`(`id`, `maxAmount`, `roleFk`) INSERT INTO `vn`.`roleCreditLimit`(`id`, `maxAmount`, `roleFk`)
VALUES VALUES
(1, 9999999, 20), (1, 9999999, 20),
(2, 10000, 21), (2, 10000, 21),
@ -549,15 +555,6 @@ INSERT INTO `vn`.`supplierActivity`(`code`, `name`)
('flowerPlants', 'Wholesale of flowers and plants'), ('flowerPlants', 'Wholesale of flowers and plants'),
('vegetablesFruits', 'Fruit and vegetable trade'); ('vegetablesFruits', 'Fruit and vegetable trade');
INSERT INTO `vn`.`supplierAddress`(`id`, `supplierFk`, `nickname`, `street`, `provinceFk`, `postalCode`, `city`, `phone`, `mobile`)
VALUES
(1, 1, 'Ace Chemicals', 'The Midtown', 1, '46000', 'Gotham', '111111111', '222222222'),
(2, 1, 'Arkham Asylum', 'Grand Avenue', 1, '46000', 'Gotham', '111111111', '222222222'),
(3, 2, 'Wayne Tower', 'Grand Avenue', 1, '46000', 'Gotham', '111111111', '222222222'),
(4, 2, 'Bank of Gotham', 'Founders Island', 1, '46000', 'Gotham', '111111111', '222222222'),
(5, 442, 'GCR building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222'),
(6, 442, 'The Gotham Tonight building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222');
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`, `commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`, `healthRegister`) INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`, `commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`, `healthRegister`)
VALUES VALUES
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, util.VN_CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'), (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, util.VN_CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'),
@ -568,6 +565,15 @@ INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`
(791, 'Bros SL', 'Bros nick', 5115000791, 1, '37718083S', 0, util.VN_CURDATE(), 1, 'supplier address 7', 'ASGARD', 3, 46600, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'), (791, 'Bros SL', 'Bros nick', 5115000791, 1, '37718083S', 0, util.VN_CURDATE(), 1, 'supplier address 7', 'ASGARD', 3, 46600, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'),
(1381, 'Ornamentales', 'Ornamentales', 7185001381, 1, '07972486L', 0, util.VN_CURDATE(), 1, 'supplier address 4', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'); (1381, 'Ornamentales', 'Ornamentales', 7185001381, 1, '07972486L', 0, util.VN_CURDATE(), 1, 'supplier address 4', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V');
INSERT INTO `vn`.`supplierAddress`(`id`, `supplierFk`, `nickname`, `street`, `provinceFk`, `postalCode`, `city`, `phone`, `mobile`)
VALUES
(1, 1, 'Ace Chemicals', 'The Midtown', 1, '46000', 'Gotham', '111111111', '222222222'),
(2, 1, 'Arkham Asylum', 'Grand Avenue', 1, '46000', 'Gotham', '111111111', '222222222'),
(3, 2, 'Wayne Tower', 'Grand Avenue', 1, '46000', 'Gotham', '111111111', '222222222'),
(4, 2, 'Bank of Gotham', 'Founders Island', 1, '46000', 'Gotham', '111111111', '222222222'),
(5, 442, 'GCR building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222'),
(6, 442, 'The Gotham Tonight building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222');
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`) INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
VALUES VALUES
(1, 1, 123121212, 654789123, 'supplier1@email.es', 'observation1', 'the boss'), (1, 1, 123121212, 654789123, 'supplier1@email.es', 'observation1', 'the boss'),
@ -628,7 +634,7 @@ INSERT INTO `vn`.`invoiceOutTax` (`invoiceOutFk`, `taxableBase`, `vat`, `pgcFk`)
(4, 8.07, 0.81, 4770000010), (4, 8.07, 0.81, 4770000010),
(5, 8.07, 0.81, 4770000010); (5, 8.07, 0.81, 4770000010);
INSERT INTO `vn`.`expence`(`id`, `name`, `isWithheld`) INSERT INTO `vn`.`expense`(`id`, `name`, `isWithheld`)
VALUES VALUES
(2000000000, 'Inmovilizado pendiente', 0), (2000000000, 'Inmovilizado pendiente', 0),
(2000000001, 'Compra de bienes de inmovilizado', 0), (2000000001, 'Compra de bienes de inmovilizado', 0),
@ -640,7 +646,7 @@ INSERT INTO `vn`.`expence`(`id`, `name`, `isWithheld`)
(7050000000, 'Prestacion de servicios', 1); (7050000000, 'Prestacion de servicios', 1);
INSERT INTO `vn`.`invoiceOutExpence`(`id`, `invoiceOutFk`, `amount`, `expenceFk`, `created`) INSERT INTO `vn`.`invoiceOutExpense`(`id`, `invoiceOutFk`, `amount`, `expenseFk`, `created`)
VALUES VALUES
(1, 1, 813.06, 2000000000, util.VN_CURDATE()), (1, 1, 813.06, 2000000000, util.VN_CURDATE()),
(2, 1, 33.80, 4751000000, util.VN_CURDATE()), (2, 1, 33.80, 4751000000, util.VN_CURDATE()),
@ -765,7 +771,7 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
-- FIX for state hours on local, inter_afterInsert -- FIX for state hours on local, inter_afterInsert
-- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND); -- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND);
INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`) INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `userFk`, `created`)
VALUES VALUES
(1, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)), (1, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)),
(2, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)), (2, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)),
@ -809,6 +815,7 @@ INSERT INTO `vn`.`config`(`id`, `mdbServer`, `fakeEmail`, `defaultersMaxAmount`,
VALUES VALUES
(1, 'beta-server', 'nightmare@mydomain.com', '200', DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH)); (1, 'beta-server', 'nightmare@mydomain.com', '200', DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH));
INSERT INTO `vn`.`greugeType`(`id`, `name`, `code`) INSERT INTO `vn`.`greugeType`(`id`, `name`, `code`)
VALUES VALUES
(1, 'Diff', 'diff'), (1, 'Diff', 'diff'),
@ -920,7 +927,7 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
('SER', 'Services'), ('SER', 'Services'),
('VT', 'Sales'); ('VT', 'Sales');
INSERT INTO `vn`.`item`(`id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, INSERT INTO `vn`.`item`(`id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenseFk`,
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `packingShelve`, `weightByPiece`) `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `packingShelve`, `weightByPiece`)
VALUES VALUES
(1, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'EMB', 0, NULL, 'V', 0, 15,3), (1, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'EMB', 0, NULL, 'V', 0, 15,3),
@ -966,6 +973,10 @@ INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPack
('cc', 1640038.00, 56.00, 220.00, 128.00, 1, util.VN_CURDATE(), 15, 90.00), ('cc', 1640038.00, 56.00, 220.00, 128.00, 1, util.VN_CURDATE(), 15, 90.00),
('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, util.VN_CURDATE(), 16, 0.00); ('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, util.VN_CURDATE(), 16, 0.00);
INSERT INTO `vn`.`packagingConfig`(`upperGap`, `defaultSmallPackageFk`, `defaultBigPackageFk`)
VALUES
('10', 1, 'pallet 100');
INSERT INTO `vn`.`expeditionStateType`(`id`, `description`, `code`) INSERT INTO `vn`.`expeditionStateType`(`id`, `description`, `code`)
VALUES VALUES
(1, 'En reparto', 'ON DELIVERY'), (1, 'En reparto', 'ON DELIVERY'),
@ -1933,7 +1944,7 @@ INSERT INTO `vn`.`ticketRequest`(`id`, `description`, `requesterFk`, `attenderFk
(4, 'Melee weapon combat first 15cm', 18, 35, 15, NULL, 1.30, NULL, NULL, 11, util.VN_CURDATE()), (4, 'Melee weapon combat first 15cm', 18, 35, 15, NULL, 1.30, NULL, NULL, 11, util.VN_CURDATE()),
(5, 'Melee weapon combat first 15cm', 18, 35, 15, 4, 1.30, 0, NULL, 18, util.VN_CURDATE()); (5, 'Melee weapon combat first 15cm', 18, 35, 15, 4, 1.30, 0, NULL, 18, util.VN_CURDATE());
INSERT INTO `vn`.`ticketServiceType`(`id`, `name`, `expenceFk`) INSERT INTO `vn`.`ticketServiceType`(`id`, `name`, `expenseFk`)
VALUES VALUES
(1, 'Porte Agencia', 7001000000), (1, 'Porte Agencia', 7001000000),
(2, 'Portes Retorno', 7001000000), (2, 'Portes Retorno', 7001000000),
@ -2337,9 +2348,11 @@ INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `weekDays`)
(8, 'indefinitely', 'mon,tue,wed,thu,fri,sat,sun'), (8, 'indefinitely', 'mon,tue,wed,thu,fri,sat,sun'),
(10, 'indefinitely', 'mon,tue,wed,thu,fri,sat,sun'); (10, 'indefinitely', 'mon,tue,wed,thu,fri,sat,sun');
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `started`, `ended`) INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `started`, `ended`, `weekDays`)
VALUES VALUES
(9, 'range', DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR), DATE_ADD(util.VN_CURDATE(), INTERVAL +1 YEAR)); (9, 'range', DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR), DATE_ADD(util.VN_CURDATE(), INTERVAL +1 YEAR), 'mon'),
(9, 'range', util.VN_CURDATE(), NULL, 'tue'),
(9, 'range', NULL, util.VN_CURDATE(), 'wed');
INSERT INTO `vn`.`workerTimeControl`(`userFk`, `timed`, `manual`, `direction`, `isSendMail`) INSERT INTO `vn`.`workerTimeControl`(`userFk`, `timed`, `manual`, `direction`, `isSendMail`)
VALUES VALUES
@ -2555,7 +2568,7 @@ INSERT INTO `vn`.`duaInvoiceIn`(`id`, `duaFk`, `invoiceInFk`)
(9, 9, 9), (9, 9, 9),
(10, 10, 10); (10, 10, 10);
INSERT INTO `vn`.`invoiceInTax` (`invoiceInFk`, `taxableBase`, `expenceFk`, `foreignValue`, `taxTypeSageFk`, `transactionTypeSageFk`) INSERT INTO `vn`.`invoiceInTax` (`invoiceInFk`, `taxableBase`, `expenseFk`, `foreignValue`, `taxTypeSageFk`, `transactionTypeSageFk`)
VALUES VALUES
(1, 99.99, '2000000000', NULL, NULL, NULL), (1, 99.99, '2000000000', NULL, NULL, NULL),
(2, 999.99, '2000000000', NULL, NULL, NULL), (2, 999.99, '2000000000', NULL, NULL, NULL),
@ -2887,7 +2900,9 @@ INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)
INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) INSERT INTO `vn`.`payDemDetail` (`id`, `detail`)
VALUES VALUES
(1, 1); (1, 1),
(2, 20),
(7, 1);
INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`, `payMethodFk`, `businessTypeFk`) INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`, `payMethodFk`, `businessTypeFk`)
VALUES VALUES
@ -2952,9 +2967,9 @@ INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`)
(2, 1, 50, 2), (2, 1, 50, 2),
(3, 1, 0, 3); (3, 1, 0, 3);
INSERT INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `renewInterval`) INSERT INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `courtesyTime`, `renewInterval`)
VALUES VALUES
(1, 21600, 300); (1, 21600, 60, 300);
INSERT INTO `vn`.`travelConfig` (`id`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `companyFk`) INSERT INTO `vn`.`travelConfig` (`id`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `companyFk`)
VALUES VALUES
@ -2994,3 +3009,8 @@ INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`)
(1, 'Error in VAT calculation'), (1, 'Error in VAT calculation'),
(2, 'Error in sales details'), (2, 'Error in sales details'),
(3, 'Error in customer data'); (3, 'Error in customer data');
INSERT INTO `vn`.`docuwareTablet` (`tablet`,`description`)
VALUES
('Tablet1','Jarvis tablet'),
('Tablet2','Avengers tablet');

File diff suppressed because it is too large Load Diff

View File

@ -45,12 +45,12 @@ TABLES=(
alertLevel alertLevel
bookingPlanner bookingPlanner
businessType businessType
cplusInvoiceType472 siiTypeInvoiceIn
cplusInvoiceType477 siiTypeInvoiceOut
cplusRectificationType cplusRectificationType
cplusSubjectOp cplusSubjectOp
cplusTaxBreak cplusTaxBreak
cplusTrascendency472 siiTrascendencyInvoiceIn
claimResponsible claimResponsible
claimReason claimReason
claimRedelivery claimRedelivery
@ -68,6 +68,8 @@ TABLES=(
volumeConfig volumeConfig
workCenter workCenter
companyI18n companyI18n
workerTimeControlError
silexACL
) )
dump_tables ${TABLES[@]} dump_tables ${TABLES[@]}

View File

@ -145,6 +145,7 @@ export default {
adController: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adController"]', adController: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adController"]',
adUser: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adUser"]', adUser: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adUser"]',
adPassword: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adPassword"]', adPassword: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adPassword"]',
userDn: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.userDn"]',
verifyCert: 'vn-account-samba vn-check[ng-model="$ctrl.config.verifyCert"]', verifyCert: 'vn-account-samba vn-check[ng-model="$ctrl.config.verifyCert"]',
save: 'vn-account-samba vn-submit' save: 'vn-account-samba vn-submit'
}, },
@ -722,7 +723,7 @@ export default {
isFullMovable: 'vn-check[ng-model="filter.isFullMovable"]', isFullMovable: 'vn-check[ng-model="filter.isFullMovable"]',
warehouseFk: 'vn-autocomplete[label="Warehouse"]', warehouseFk: 'vn-autocomplete[label="Warehouse"]',
tableButtonSearch: 'vn-button[vn-tooltip="Search"]', tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
moveButton: 'vn-button[vn-tooltip="Advance tickets"]', moveButton: 'vn-button[vn-tooltip="Advance tickets with negatives"]',
acceptButton: '.vn-confirm.shown button[response="accept"]', acceptButton: '.vn-confirm.shown button[response="accept"]',
firstCheck: 'tbody > tr:nth-child(2) > td > vn-check', firstCheck: 'tbody > tr:nth-child(2) > td > vn-check',
tableId: 'vn-textfield[name="id"]', tableId: 'vn-textfield[name="id"]',

View File

@ -26,7 +26,7 @@ describe('Route create path', () => {
await page.waitToClick(selectors.createRouteView.submitButton); await page.waitToClick(selectors.createRouteView.submitButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Access denied'); expect(message.text).toContain('Access Denied');
}); });
}); });

View File

@ -22,7 +22,7 @@ describe('Travel basic data path', () => {
await page.waitForState('travel.card.basicData'); await page.waitForState('travel.card.basicData');
}); });
it('should set a wrong delivery date then receive an error on submit', async() => { it('should throw error if try move a travel with entries', async() => {
const lastMonth = Date.vnNew(); const lastMonth = Date.vnNew();
lastMonth.setMonth(lastMonth.getMonth() - 1); lastMonth.setMonth(lastMonth.getMonth() - 1);
@ -30,6 +30,23 @@ describe('Travel basic data path', () => {
await page.waitToClick(selectors.travelBasicData.save); await page.waitToClick(selectors.travelBasicData.save);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Cannot past travels with entries');
});
it('should set a wrong delivery date then receive an error on submit', async() => {
await page.loginAndModule('buyer', 'travel');
await page.write(selectors.travelIndex.generalSearchFilter, '4');
await page.keyboard.press('Enter');
await page.accessToSection('travel.card.basicData');
await page.waitForState('travel.card.basicData');
const lastMonth = Date.vnNew();
lastMonth.setMonth(lastMonth.getMonth() - 2);
await page.pickDate(selectors.travelBasicData.deliveryDate, lastMonth);
await page.waitToClick(selectors.travelBasicData.save);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Landing cannot be lesser than shipment'); expect(message.text).toContain('Landing cannot be lesser than shipment');
}); });
@ -39,7 +56,7 @@ describe('Travel basic data path', () => {
await page.waitToClick(selectors.travelBasicData.undoChanges); await page.waitToClick(selectors.travelBasicData.undoChanges);
const result = await page.waitToGetProperty(selectors.travelBasicData.reference, 'value'); const result = await page.waitToGetProperty(selectors.travelBasicData.reference, 'value');
expect(result).toEqual('third travel'); expect(result).toEqual('fourth travel');
}); });
it('should now edit the whole form then save', async() => { it('should now edit the whole form then save', async() => {

View File

@ -23,18 +23,6 @@ describe('Account Accounts path', () => {
expect(message.text).toContain('Roles synchronized!'); expect(message.text).toContain('Roles synchronized!');
}); });
it('should sync user', async() => {
await page.waitToClick(selectors.accountAccounts.syncUser);
await page.write(selectors.accountAccounts.syncUserName, 'sysadmin');
await page.write(selectors.accountAccounts.syncUserPassword, 'nightmare');
await page.waitToClick(selectors.accountAccounts.buttonAccept);
const message = await page.waitForSnackbar();
expect(message.text).toContain('User synchronized!');
});
it('should relogin', async() => { it('should relogin', async() => {
await page.loginAndModule('sysadmin', 'account'); await page.loginAndModule('sysadmin', 'account');
await page.accessToSection('account.accounts'); await page.accessToSection('account.accounts');

View File

@ -20,8 +20,9 @@ describe('Account Samba path', () => {
await page.waitToClick(selectors.accountSamba.checkEnable); await page.waitToClick(selectors.accountSamba.checkEnable);
await page.write(selectors.accountSamba.adDomain, '1234'); await page.write(selectors.accountSamba.adDomain, '1234');
await page.write(selectors.accountSamba.adController, '1234'); await page.write(selectors.accountSamba.adController, '1234');
await page.write(selectors.accountSamba.adUser, 'nightmare'); await page.write(selectors.accountSamba.adUser, 'sysadmin');
await page.write(selectors.accountSamba.adPassword, 'sysadmin'); await page.write(selectors.accountSamba.adPassword, 'nightmare');
await page.write(selectors.accountSamba.userDn, 'testDn');
await page.waitToClick(selectors.accountSamba.verifyCert); await page.waitToClick(selectors.accountSamba.verifyCert);
await page.waitToClick(selectors.accountSamba.save); await page.waitToClick(selectors.accountSamba.save);

View File

@ -3,4 +3,4 @@ Could not contact the server: Could not contact the server, make sure you have a
Please enter your username: Please enter your username Please enter your username: Please enter your username
It seems that the server has fall down: It seems that the server has fall down, wait a few minutes and try again It seems that the server has fall down: It seems that the server has fall down, wait a few minutes and try again
Session has expired: Your session has expired, please login again Session has expired: Your session has expired, please login again
Access denied: Access denied Access Denied: Access Denied

View File

@ -3,5 +3,5 @@ Could not contact the server: No se ha podido contactar con el servidor, asegura
Please enter your username: Por favor introduce tu nombre de usuario Please enter your username: Por favor introduce tu nombre de usuario
It seems that the server has fall down: Parece que el servidor se ha caído, espera unos minutos e inténtalo de nuevo It seems that the server has fall down: Parece que el servidor se ha caído, espera unos minutos e inténtalo de nuevo
Session has expired: Tu sesión ha expirado, por favor vuelve a iniciar sesión Session has expired: Tu sesión ha expirado, por favor vuelve a iniciar sesión
Access denied: Acción no permitida Access Denied: Acción no permitida
Direction not found: Dirección no encontrada Direction not found: Dirección no encontrada

View File

@ -82,7 +82,7 @@ export default class Token {
if (!data) return; if (!data) return;
this.renewPeriod = data.renewPeriod; this.renewPeriod = data.renewPeriod;
this.stopRenewer(); this.stopRenewer();
this.inservalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000); this.intervalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000);
}); });
} }
@ -103,17 +103,13 @@ export default class Token {
const token = res.data; const token = res.data;
this.set(token.id, now, token.ttl, this.remember); this.set(token.id, now, token.ttl, this.remember);
}) })
.catch(res => {
if (res.data?.error?.code !== 'periodNotExceeded')
throw res;
})
.finally(() => { .finally(() => {
this.checking = false; this.checking = false;
}); });
} }
stopRenewer() { stopRenewer() {
clearInterval(this.inservalId); clearInterval(this.intervalId);
} }
} }
Token.$inject = ['vnInterceptor', '$http', '$rootScope']; Token.$inject = ['vnInterceptor', '$http', '$rootScope'];

View File

@ -18,6 +18,7 @@ Show summary: Mostrar vista previa
What is new: Novedades de la versión What is new: Novedades de la versión
Settings: Ajustes Settings: Ajustes
There is a new version, click here to reload: Hay una nueva versión, pulse aquí para recargar There is a new version, click here to reload: Hay una nueva versión, pulse aquí para recargar
This ticket is locked: Este ticket está bloqueado
# Actions # Actions

View File

@ -120,7 +120,7 @@ function $exceptionHandler(vnApp, $window, $state, $injector) {
messageT = 'Invalid login'; messageT = 'Invalid login';
break; break;
case 403: case 403:
messageT = 'Access denied'; messageT = exception.data?.error?.message || 'Access Denied';
break; break;
case 502: case 502:
messageT = 'It seems that the server has fall down'; messageT = 'It seems that the server has fall down';

View File

@ -183,7 +183,7 @@
"Social name should be uppercase": "Social name should be uppercase", "Social name should be uppercase": "Social name should be uppercase",
"Street should be uppercase": "Street should be uppercase", "Street should be uppercase": "Street should be uppercase",
"You don't have enough privileges.": "You don't have enough privileges.", "You don't have enough privileges.": "You don't have enough privileges.",
"This ticket is locked.": "This ticket is locked.", "This ticket is locked": "This ticket is locked",
"This ticket is not editable.": "This ticket is not editable.", "This ticket is not editable.": "This ticket is not editable.",
"The ticket doesn't exist.": "The ticket doesn't exist.", "The ticket doesn't exist.": "The ticket doesn't exist.",
"The sales do not exists": "The sales do not exists", "The sales do not exists": "The sales do not exists",
@ -196,6 +196,9 @@
"Negative basis of tickets: 23": "Negative basis of tickets: 23", "Negative basis of tickets: 23": "Negative basis of tickets: 23",
"Booking completed": "Booking complete", "Booking completed": "Booking complete",
"The ticket is in preparation": "The ticket [{{ticketId}}]({{{ticketUrl}}}) of the sales person {{salesPersonId}} is in preparation", "The ticket is in preparation": "The ticket [{{ticketId}}]({{{ticketUrl}}}) of the sales person {{salesPersonId}} is in preparation",
"You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets" "You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets",
"Try again": "Try again",
"keepPrice": "keepPrice",
"Cannot past travels with entries": "Cannot past travels with entries",
"It was not able to remove the next expeditions:": "It was not able to remove the next expeditions: {{expeditions}}"
} }

View File

@ -224,7 +224,7 @@
"date in the future": "Fecha en el futuro", "date in the future": "Fecha en el futuro",
"reference duplicated": "Referencia duplicada", "reference duplicated": "Referencia duplicada",
"This ticket is already a refund": "Este ticket ya es un abono", "This ticket is already a refund": "Este ticket ya es un abono",
"isWithoutNegatives": "isWithoutNegatives", "isWithoutNegatives": "Sin negativos",
"routeFk": "routeFk", "routeFk": "routeFk",
"Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador", "Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador",
"No hay un contrato en vigor": "No hay un contrato en vigor", "No hay un contrato en vigor": "No hay un contrato en vigor",
@ -313,7 +313,7 @@
"You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado",
"This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado", "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado",
"You don't have enough privileges.": "No tienes suficientes permisos.", "You don't have enough privileges.": "No tienes suficientes permisos.",
"This ticket is locked.": "Este ticket está bloqueado.", "This ticket is locked": "Este ticket está bloqueado.",
"This ticket is not editable.": "Este ticket no es editable.", "This ticket is not editable.": "Este ticket no es editable.",
"The ticket doesn't exist.": "No existe el ticket.", "The ticket doesn't exist.": "No existe el ticket.",
"Social name should be uppercase": "La razón social debe ir en mayúscula", "Social name should be uppercase": "La razón social debe ir en mayúscula",
@ -324,7 +324,12 @@
"The response is not a PDF": "La respuesta no es un PDF", "The response is not a PDF": "La respuesta no es un PDF",
"Booking completed": "Reserva completada", "Booking completed": "Reserva completada",
"The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación", "The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación",
"The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mímina", "Incoterms data for consignee is missing": "Faltan los datos de los Incoterms para el consignatario",
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mímina", "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada",
"The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada" "User disabled": "Usuario desactivado",
"The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima",
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima",
"Cannot past travels with entries": "No se pueden pasar envíos con entradas",
"It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}",
"This user does not have an assigned tablet": "Este usuario no tiene tablet asignada"
} }

View File

@ -1,6 +1,5 @@
module.exports = () => { module.exports = () => {
Date.vnUTC = () => { Date.vnUTC = (env = process.env.NODE_ENV) => {
const env = process.env.NODE_ENV;
if (!env || env === 'development') if (!env || env === 'development')
return new Date(Date.UTC(2001, 0, 1, 11)); return new Date(Date.UTC(2001, 0, 1, 11));

View File

@ -39,7 +39,7 @@
"./middleware/salix-version": {} "./middleware/salix-version": {}
}, },
"parse": { "parse": {
"body-parser#json":{} "body-parser#json":{}
}, },
"routes": { "routes": {
"loopback#rest": { "loopback#rest": {

View File

@ -1,3 +1,4 @@
const NotFoundError = require('vn-loopback/util/not-found-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('test', { Self.remoteMethod('test', {
@ -9,7 +10,8 @@ module.exports = Self => {
}); });
Self.test = async function() { Self.test = async function() {
let connector = await Self.getSynchronizer(); const connector = await Self.getLinker();
if (!connector) throw new NotFoundError('Linker not configured');
await connector.test(); await connector.test();
}; };
}; };

View File

@ -2,7 +2,7 @@ const {models} = require('vn-loopback/server/server');
describe('account changePassword()', () => { describe('account changePassword()', () => {
const userId = 70; const userId = 70;
const unauthCtx = { const unAuthCtx = {
req: { req: {
headers: {}, headers: {},
connection: { connection: {
@ -79,7 +79,7 @@ describe('account changePassword()', () => {
passExpired: yesterday passExpired: yesterday
} }
, options); , options);
await models.VnUser.signIn(unauthCtx, 'trainee', 'nightmare', options); await models.VnUser.signIn(unAuthCtx, 'trainee', 'nightmare', options);
} catch (e) { } catch (e) {
if (e.message != 'Pass expired') if (e.message != 'Pass expired')
throw e; throw e;

View File

@ -1,3 +1,4 @@
const ForbiddenError = require('vn-loopback/util/forbiddenError');
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('sync', { Self.remoteMethod('sync', {
@ -25,21 +26,46 @@ module.exports = Self => {
}); });
Self.sync = async function(userName, password, force, options) { Self.sync = async function(userName, password, force, options) {
const models = Self.app.models;
const myOptions = {}; const myOptions = {};
let tx;
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const models = Self.app.models; if (!myOptions.transaction) {
const user = await models.VnUser.findOne({ tx = await Self.beginTransaction({});
fields: ['id'], myOptions.transaction = tx;
where: {name: userName} };
}, myOptions);
const isSync = !await models.UserSync.exists(userName, myOptions);
if (!force && isSync && user) return; try {
await models.AccountConfig.syncUser(userName, password); const user = await models.VnUser.findOne({
await models.UserSync.destroyById(userName, myOptions); fields: ['id', 'password'],
where: {name: userName}
}, myOptions);
if (user && password && !await user.hasPassword(password))
throw new ForbiddenError('Wrong password');
const isSync = !await models.UserSync.exists(userName, myOptions);
if (!force && isSync && user) {
if (tx) await tx.rollback();
return;
}
await Self.rawSql(`
SELECT id
FROM account.user
WHERE id = ?
FOR UPDATE`, [user.id], myOptions);
await models.AccountConfig.syncUser(userName, password);
await models.UserSync.destroyById(userName, myOptions);
if (tx) await tx.commit();
} catch (err) {
if (tx) await tx.rollback();
throw err;
}
}; };
}; };

View File

@ -3,14 +3,14 @@ const app = require('vn-loopback/server/server');
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
module.exports = function(Self, options) { module.exports = function(Self, options) {
require('../methods/account-synchronizer/test')(Self); require('../methods/account-linker/test')(Self);
Self.once('attached', function() { Self.once('attached', function() {
app.models.AccountConfig.addSynchronizer(Self); app.models.AccountConfig.addLinker(Self);
}); });
/** /**
* Mixin for user synchronizers. * Mixin for account linkers.
* *
* @property {Array<Model>} $ * @property {Array<Model>} $
* @property {Object} accountConfig * @property {Object} accountConfig
@ -18,12 +18,12 @@ module.exports = function(Self, options) {
*/ */
let Mixin = { let Mixin = {
/** /**
* Initalizes the synchronizer. * Initalizes the linker.
*/ */
async init() {}, async init() {},
/** /**
* Deinitalizes the synchronizer. * Deinitalizes the linker.
*/ */
async deinit() {}, async deinit() {},
@ -57,7 +57,7 @@ module.exports = function(Self, options) {
async syncRoles() {}, async syncRoles() {},
/** /**
* Tests synchronizer configuration. * Tests linker configuration.
*/ */
async test() { async test() {
try { try {

View File

@ -35,6 +35,9 @@
"SambaConfig": { "SambaConfig": {
"dataSource": "vn" "dataSource": "vn"
}, },
"SignInLog": {
"dataSource": "vn"
},
"Sip": { "Sip": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -3,94 +3,85 @@ const models = require('vn-loopback/server/server').models;
module.exports = Self => { module.exports = Self => {
Object.assign(Self, { Object.assign(Self, {
synchronizers: [], linkers: [],
addSynchronizer(synchronizer) { addLinker(linker) {
this.synchronizers.push(synchronizer); this.linkers.push(linker);
}, },
async getInstance() { async initEngine() {
let instance = await Self.findOne({ const accountConfig = await Self.findOne({
fields: ['homedir', 'shell', 'idBase'] fields: ['homedir', 'shell', 'idBase']
}); });
await instance.synchronizerInit(); const mailConfig = await models.MailConfig.findOne({
return instance; fields: ['domain']
});
const linkers = [];
for (const Linker of Self.linkers) {
const linker = await Linker.getLinker();
if (!linker) continue;
Object.assign(linker, {accountConfig});
await linker.init();
linkers.push(linker);
}
Object.assign(accountConfig, {
linkers,
domain: mailConfig.domain
});
return {
accountConfig,
linkers
};
},
async deinitEngine(engine) {
for (const linker of engine.linkers)
await linker.deinit();
},
async syncUser(userName, password) {
const engine = await Self.initEngine();
try {
await Self.syncUserBase(engine, userName, password, true);
} finally {
await Self.deinitEngine(engine);
}
}, },
async syncUsers() { async syncUsers() {
let instance = await Self.getInstance(); const engine = await Self.initEngine();
let usersToSync = new Set();
for (const linker of engine.linkers)
await linker.getUsers(usersToSync);
let usersToSync = await instance.synchronizerGetUsers();
usersToSync = Array.from(usersToSync.values()) usersToSync = Array.from(usersToSync.values())
.sort((a, b) => a.localeCompare(b)); .sort((a, b) => a.localeCompare(b));
for (let userName of usersToSync) { for (let userName of usersToSync) {
try { try {
// eslint-disable-next-line no-console
console.log(`Synchronizing user '${userName}'`); console.log(`Synchronizing user '${userName}'`);
await instance.synchronizerSyncUser(userName);
await Self.syncUserBase(engine, userName);
// eslint-disable-next-line no-console
console.log(` -> User '${userName}' sinchronized`); console.log(` -> User '${userName}' sinchronized`);
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console
console.error(` -> User '${userName}' synchronization error:`, err.message); console.error(` -> User '${userName}' synchronization error:`, err.message);
} }
} }
await instance.synchronizerDeinit(); await Self.deinitEngine(engine);
await Self.syncRoles(); await Self.syncRoles();
}, },
async syncUser(userName, password) { async syncUserBase(engine, userName, password, syncGroups) {
let instance = await Self.getInstance();
try {
await instance.synchronizerSyncUser(userName, password, true);
} finally {
await instance.synchronizerDeinit();
}
},
async syncRoles() {
let instance = await Self.getInstance();
try {
await instance.synchronizerSyncRoles();
} finally {
await instance.synchronizerDeinit();
}
},
async getSynchronizer() {
return await Self.findOne();
}
});
Object.assign(Self.prototype, {
async synchronizerInit() {
let mailConfig = await models.MailConfig.findOne({
fields: ['domain']
});
let synchronizers = [];
for (let Synchronizer of Self.synchronizers) {
let synchronizer = await Synchronizer.getSynchronizer();
if (!synchronizer) continue;
Object.assign(synchronizer, {
accountConfig: this
});
await synchronizer.init();
synchronizers.push(synchronizer);
}
Object.assign(this, {
synchronizers,
domain: mailConfig.domain
});
},
async synchronizerDeinit() {
for (let synchronizer of this.synchronizers)
await synchronizer.deinit();
},
async synchronizerSyncUser(userName, password, syncGroups) {
if (!userName) return; if (!userName) return;
userName = userName.toLowerCase(); userName = userName.toLowerCase();
@ -98,7 +89,7 @@ module.exports = Self => {
if (['administrator', 'root'].indexOf(userName) >= 0) if (['administrator', 'root'].indexOf(userName) >= 0)
return; return;
let user = await models.VnUser.findOne({ const user = await models.VnUser.findOne({
where: {name: userName}, where: {name: userName},
fields: [ fields: [
'id', 'id',
@ -130,27 +121,28 @@ module.exports = Self => {
] ]
}); });
let info = { const info = {
user, user,
hasAccount: false hasAccount: false
}; };
if (user) { if (user) {
let exists = await models.Account.exists(user.id); const exists = await models.Account.exists(user.id);
const {accountConfig} = engine;
Object.assign(info, { Object.assign(info, {
hasAccount: user.active && exists, hasAccount: user.active && exists,
corporateMail: `${userName}@${this.domain}`, corporateMail: `${userName}@${accountConfig.domain}`,
uidNumber: this.idBase + user.id uidNumber: accountConfig.idBase + user.id
}); });
} }
let errs = []; const errs = [];
for (let synchronizer of this.synchronizers) { for (const linker of engine.linkers) {
try { try {
await synchronizer.syncUser(userName, info, password); await linker.syncUser(userName, info, password);
if (syncGroups) if (syncGroups)
await synchronizer.syncUserGroups(userName, info); await linker.syncUserGroups(userName, info);
} catch (err) { } catch (err) {
errs.push(err); errs.push(err);
} }
@ -159,18 +151,16 @@ module.exports = Self => {
if (errs.length) throw errs[0]; if (errs.length) throw errs[0];
}, },
async synchronizerGetUsers() { async syncRoles() {
let usersToSync = new Set(); const engine = await Self.initEngine();
try {
await Self.rawSql(`CALL account.role_sync`);
for (let synchronizer of this.synchronizers) for (const linker of engine.linkers)
await synchronizer.getUsers(usersToSync); await linker.syncRoles();
} finally {
return usersToSync; await Self.deinitEngine(engine);
}, }
async synchronizerSyncRoles() {
for (let synchronizer of this.synchronizers)
await synchronizer.syncRoles();
} }
}); });
}; };

View File

@ -5,9 +5,9 @@ const crypto = require('crypto');
const nthash = require('smbhash').nthash; const nthash = require('smbhash').nthash;
module.exports = Self => { module.exports = Self => {
const shouldSync = process.env.NODE_ENV === 'production'; const shouldSync = process.env.NODE_ENV !== 'test';
Self.getSynchronizer = async function() { Self.getLinker = async function() {
return await Self.findOne({ return await Self.findOne({
fields: [ fields: [
'server', 'server',
@ -24,6 +24,7 @@ module.exports = Self => {
this.client = ldap.createClient({ this.client = ldap.createClient({
url: this.server url: this.server
}); });
this.client.on('error', () => {});
await this.client.bind(this.rdn, this.password); await this.client.bind(this.rdn, this.password);
}, },
@ -140,6 +141,7 @@ module.exports = Self => {
try { try {
if (shouldSync) if (shouldSync)
await client.del(dn); await client.del(dn);
// eslint-disable-next-line no-console
console.log(` -> User '${userName}' removed from LDAP`); console.log(` -> User '${userName}' removed from LDAP`);
} catch (e) { } catch (e) {
if (e.name !== 'NoSuchObjectError') throw e; if (e.name !== 'NoSuchObjectError') throw e;

View File

@ -7,7 +7,7 @@
} }
}, },
"mixins": { "mixins": {
"AccountSynchronizer": {} "AccountLinker": {}
}, },
"properties": { "properties": {
"id": { "id": {

Some files were not shown because too many files have changed in this diff Show More