#5834 - billingDataAutoFillBic #1821
|
@ -3,12 +3,20 @@
|
|||
// Carácter predeterminado de final de línea.
|
||||
"files.eol": "\n",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"search.useIgnoreFiles": false,
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||
"eslint.format.enable": true,
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||
}
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"salix",
|
||||
"fdescribe",
|
||||
"Loggable"
|
||||
]
|
||||
}
|
||||
|
|
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -5,6 +5,42 @@ 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/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2404.01] - 2024-01-25
|
||||
|
||||
### Added
|
||||
### Changed
|
||||
### Fixed
|
||||
|
||||
|
||||
## [2402.01] - 2024-01-11
|
||||
|
||||
### Added
|
||||
### Changed
|
||||
### 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
|
||||
|
||||
### Added
|
||||
|
|
10
Dockerfile
10
Dockerfile
|
@ -1,4 +1,4 @@
|
|||
FROM debian:bullseye-slim
|
||||
FROM debian:bookworm-slim
|
||||
ENV TZ Europe/Madrid
|
||||
|
||||
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 \
|
||||
libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 \
|
||||
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/* \
|
||||
&& npm -g install pm2
|
||||
|
||||
|
|
40
README.md
40
README.md
|
@ -8,7 +8,7 @@ Salix is also the scientific name of a beautifull tree! :)
|
|||
|
||||
Required applications.
|
||||
|
||||
* Node.js >= 16.x LTS
|
||||
* Node.js
|
||||
* Docker
|
||||
* Git
|
||||
|
||||
|
@ -17,20 +17,7 @@ You will need to install globally the following items.
|
|||
$ sudo npm install -g jest gulp-cli
|
||||
```
|
||||
|
||||
For the usage of jest --watch on macOs.
|
||||
```
|
||||
$ 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
|
||||
## Installing dependencies and launching
|
||||
|
||||
Pull from repository.
|
||||
|
||||
|
@ -76,29 +63,6 @@ In Visual Studio Code we use the ESLint extension.
|
|||
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
|
||||
|
||||
* [angularjs](https://angularjs.org/)
|
||||
|
|
|
@ -49,7 +49,7 @@ module.exports = Self => {
|
|||
ish.packing,
|
||||
ish.grouping,
|
||||
s.isAdded,
|
||||
s.originalQuantity,
|
||||
s.originalQuantity,
|
||||
s.quantity saleQuantity,
|
||||
iss.quantity reservedQuantity,
|
||||
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 origin o ON o.id = i.originFk
|
||||
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);
|
||||
|
||||
if (print)
|
||||
|
@ -105,7 +105,7 @@ module.exports = Self => {
|
|||
LEFT JOIN vn.buy c ON c.itemFk = s.itemFk
|
||||
LEFT JOIN vn.entry e ON e.id = c.entryFk
|
||||
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`,
|
||||
[ticketId], myOptions);
|
||||
ticket.sales = [];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -22,8 +22,8 @@ module.exports = Self => {
|
|||
|
||||
Self.removeFile = async(ctx, id, options) => {
|
||||
const models = Self.app.models;
|
||||
let tx;
|
||||
const myOptions = {};
|
||||
let tx;
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
|
|
@ -24,15 +24,40 @@ describe('docuware upload()', () => {
|
|||
});
|
||||
|
||||
it('should try upload file', async() => {
|
||||
const tx = await models.Docuware.beginTransaction({});
|
||||
spyOn(ticketModel, 'deliveryNotePdf').and.returnValue(new Promise(resolve => resolve({})));
|
||||
|
||||
let error;
|
||||
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', options);
|
||||
await models.Docuware.upload(ctx, ticketIds, fileCabinetName, options);
|
||||
|
||||
await tx.rollback();
|
||||
} 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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
const models = Self.app.models;
|
||||
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 dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId);
|
||||
|
||||
|
@ -45,7 +57,7 @@ module.exports = Self => {
|
|||
const deliveryNote = await models.Ticket.deliveryNotePdf(ctx, {
|
||||
id,
|
||||
type: 'deliveryNote'
|
||||
});
|
||||
}, myOptions);
|
||||
// get ticket data
|
||||
const ticket = await models.Ticket.findById(id, {
|
||||
include: [{
|
||||
|
@ -54,7 +66,7 @@ module.exports = Self => {
|
|||
fields: ['id', 'name', 'fi']
|
||||
}
|
||||
}]
|
||||
});
|
||||
}, myOptions);
|
||||
|
||||
// upload file
|
||||
const templateJson = {
|
||||
|
@ -102,7 +114,7 @@ module.exports = Self => {
|
|||
{
|
||||
'FieldName': 'FILTRO_TABLET',
|
||||
'ItemElementName': 'string',
|
||||
'Item': 'Tablet1',
|
||||
'Item': userConfig.tabletFk,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -116,11 +128,11 @@ module.exports = Self => {
|
|||
const deleteJson = {
|
||||
'Field': [{'FieldName': 'ESTADO', 'Item': 'Pendiente eliminar', 'ItemElementName': 'String'}]
|
||||
};
|
||||
const deleteUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/Fields`;
|
||||
await axios.put(deleteUri, deleteJson, options.headers);
|
||||
const deleteUri = `${docuwareOptions.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/Fields`;
|
||||
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 data = new FormData();
|
||||
|
||||
|
@ -130,7 +142,7 @@ module.exports = Self => {
|
|||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'X-File-ModifiedDate': Date.vnNew(),
|
||||
'Cookie': options.headers.headers.Cookie,
|
||||
'Cookie': docuwareOptions.headers.headers.Cookie,
|
||||
...data.getHeaders()
|
||||
},
|
||||
};
|
||||
|
@ -141,11 +153,11 @@ module.exports = Self => {
|
|||
const $t = ctx.req.__;
|
||||
const message = $t('Failed to upload delivery note', {id});
|
||||
if (uploaded.length)
|
||||
await models.TicketTracking.setDelivered(ctx, uploaded);
|
||||
await models.TicketTracking.setDelivered(ctx, uploaded, myOptions);
|
||||
throw new UserError(message);
|
||||
}
|
||||
uploaded.push(id);
|
||||
}
|
||||
return models.TicketTracking.setDelivered(ctx, ticketIds);
|
||||
return models.TicketTracking.setDelivered(ctx, ticketIds, myOptions);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('getList', {
|
||||
description: 'Get list of the available and active notification subscriptions',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
description: 'User to modify',
|
||||
http: {source: 'path'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/getList`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getList = async(id, options) => {
|
||||
const activeNotificationsMap = new Map();
|
||||
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const availableNotificationsMap = await Self.getAvailable(id, myOptions);
|
||||
const activeNotifications = await Self.app.models.NotificationSubscription.find({
|
||||
fields: ['id', 'notificationFk'],
|
||||
include: {relation: 'notification'},
|
||||
where: {userFk: id}
|
||||
}, myOptions);
|
||||
|
||||
for (active of activeNotifications) {
|
||||
activeNotificationsMap.set(active.notificationFk, {
|
||||
id: active.id,
|
||||
notificationFk: active.notificationFk,
|
||||
name: active.notification().name,
|
||||
description: active.notification().description,
|
||||
active: true
|
||||
});
|
||||
availableNotificationsMap.delete(active.notificationFk);
|
||||
}
|
||||
|
||||
return {
|
||||
active: [...activeNotificationsMap.entries()],
|
||||
available: [...availableNotificationsMap.entries()]
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('NotificationSubscription getList()', () => {
|
||||
it('should return a list of available and active notifications of a user', async() => {
|
||||
const userId = 9;
|
||||
const {active, available} = await models.NotificationSubscription.getList(userId);
|
||||
const notifications = await models.Notification.find({});
|
||||
const totalAvailable = notifications.length - active.length;
|
||||
|
||||
expect(active.length).toEqual(2);
|
||||
expect(available.length).toEqual(totalAvailable);
|
||||
});
|
||||
});
|
|
@ -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>
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -68,7 +68,7 @@ module.exports = Self => {
|
|||
userToUpdate.hasGrant = hasGrant;
|
||||
|
||||
if (roleFk) {
|
||||
const role = await models.Role.findById(roleFk, {fields: ['name']}, myOptions);
|
||||
const role = await models.VnRole.findById(roleFk, {fields: ['name']}, myOptions);
|
||||
const hasRole = await Self.hasRole(userId, role.name, myOptions);
|
||||
|
||||
if (!hasRole)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const {models} = require('vn-loopback/server/server');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('renewToken', {
|
||||
|
@ -16,20 +16,31 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.renewToken = async function(ctx) {
|
||||
const models = Self.app.models;
|
||||
const token = ctx.req.accessToken;
|
||||
const {accessToken: token} = ctx.req;
|
||||
|
||||
const now = new Date();
|
||||
// Check if current token is valid
|
||||
|
||||
const {renewPeriod, courtesyTime} = await models.AccessTokenConfig.findOne({
|
||||
fields: ['renewPeriod', 'courtesyTime']
|
||||
});
|
||||
const now = Date.now();
|
||||
const differenceMilliseconds = now - token.created;
|
||||
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
|
||||
const isNotExceeded = differenceSeconds < renewPeriod - courtesyTime;
|
||||
if (isNotExceeded)
|
||||
return token;
|
||||
|
||||
const fields = ['renewPeriod', 'courtesyTime'];
|
||||
const accessTokenConfig = await models.AccessTokenConfig.findOne({fields});
|
||||
// Schedule to remove current token
|
||||
setTimeout(async() => {
|
||||
try {
|
||||
await Self.logout(token.id);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}, courtesyTime * 1000);
|
||||
|
||||
if (differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime)
|
||||
throw new UserError(`The renew period has not been exceeded`, 'periodNotExceeded');
|
||||
|
||||
await Self.logout(token.id);
|
||||
// Create new accessToken
|
||||
const user = await Self.findById(token.userId);
|
||||
const accessToken = await user.createAccessToken();
|
||||
|
||||
|
|
|
@ -49,8 +49,7 @@ module.exports = Self => {
|
|||
if (vnUser.twoFactor)
|
||||
throw new ForbiddenError(null, 'REQUIRES_2FA');
|
||||
}
|
||||
|
||||
return Self.validateLogin(user, password);
|
||||
return Self.validateLogin(user, password, ctx);
|
||||
};
|
||||
|
||||
Self.passExpired = async vnUser => {
|
||||
|
|
|
@ -70,7 +70,7 @@ describe('VnUser privileges()', () => {
|
|||
const tx = await models.VnUser.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const agency = await models.Role.findOne({
|
||||
const agency = await models.VnRole.findOne({
|
||||
where: {
|
||||
name: 'agency'
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
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);
|
||||
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);
|
||||
});
|
||||
});
|
|
@ -2,7 +2,7 @@ const {models} = require('vn-loopback/server/server');
|
|||
|
||||
describe('VnUser Sign-in()', () => {
|
||||
const employeeId = 1;
|
||||
const unauthCtx = {
|
||||
const unAuthCtx = {
|
||||
req: {
|
||||
headers: {},
|
||||
connection: {
|
||||
|
@ -12,10 +12,21 @@ describe('VnUser Sign-in()', () => {
|
|||
},
|
||||
args: {}
|
||||
};
|
||||
const {VnUser, AccessToken} = models;
|
||||
const {VnUser, AccessToken, SignInLog} = models;
|
||||
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() => {
|
||||
let login = await VnUser.signIn(unauthCtx, 'salesAssistant', 'nightmare');
|
||||
let login = await VnUser.signIn(unAuthCtx, 'salesAssistant', 'nightmare');
|
||||
let accessToken = await AccessToken.findById(login.token);
|
||||
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() => {
|
||||
let login = await VnUser.signIn(unauthCtx, 'PetterParker', 'nightmare');
|
||||
let login = await VnUser.signIn(unAuthCtx, 'PetterParker', 'nightmare');
|
||||
let accessToken = await AccessToken.findById(login.token);
|
||||
let ctx = {req: {accessToken: accessToken}};
|
||||
|
||||
|
@ -40,7 +51,7 @@ describe('VnUser Sign-in()', () => {
|
|||
let error;
|
||||
|
||||
try {
|
||||
await VnUser.signIn(unauthCtx, 'IDontExist', 'TotallyWrongPassword');
|
||||
await VnUser.signIn(unAuthCtx, 'IDontExist', 'TotallyWrongPassword');
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
@ -61,7 +72,7 @@ describe('VnUser Sign-in()', () => {
|
|||
const options = {transaction: tx};
|
||||
await employee.updateAttribute('twoFactor', 'email', options);
|
||||
|
||||
await VnUser.signIn(unauthCtx, 'employee', 'nightmare', options);
|
||||
await VnUser.signIn(unAuthCtx, 'employee', 'nightmare', options);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
|
@ -86,7 +97,7 @@ describe('VnUser Sign-in()', () => {
|
|||
const options = {transaction: tx};
|
||||
await employee.updateAttribute('passExpired', yesterday, options);
|
||||
|
||||
await VnUser.signIn(unauthCtx, 'employee', 'nightmare', options);
|
||||
await VnUser.signIn(unAuthCtx, 'employee', 'nightmare', options);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -139,9 +139,6 @@
|
|||
"Warehouse": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"VnUser": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"OsTicket": {
|
||||
"dataSource": "osticket"
|
||||
},
|
||||
|
@ -156,6 +153,12 @@
|
|||
},
|
||||
"ViaexpressConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"VnUser": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"VnRole": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/collection/getCollection')(Self);
|
||||
require('../methods/collection/newCollection')(Self);
|
||||
require('../methods/collection/getSectors')(Self);
|
||||
require('../methods/collection/setSaleQuantity')(Self);
|
||||
require('../methods/collection/previousLabel')(Self);
|
||||
|
|
|
@ -17,10 +17,6 @@
|
|||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
|
@ -29,12 +25,12 @@
|
|||
"relations": {
|
||||
"readRole": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"model": "VnRole",
|
||||
"foreignKey": "readRoleFk"
|
||||
},
|
||||
"writeRole": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"model": "VnRole",
|
||||
"foreignKey": "writeRoleFk"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "docuwareTablet",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "docuwareTablet"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"tablet": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,12 +46,12 @@
|
|||
},
|
||||
"readRole": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"model": "VnRole",
|
||||
"foreignKey": "readRoleFk"
|
||||
},
|
||||
"writeRole": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"model": "VnRole",
|
||||
"foreignKey": "writeRoleFk"
|
||||
}
|
||||
},
|
||||
|
@ -64,4 +64,3 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -24,8 +24,8 @@
|
|||
},
|
||||
"role": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"model": "VnRole",
|
||||
"foreignKey": "roleFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +1,74 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
require('../methods/notification/getList')(Self);
|
||||
|
||||
Self.observe('before save', async function(ctx) {
|
||||
await checkModifyPermission(ctx);
|
||||
});
|
||||
|
||||
Self.observe('before delete', async function(ctx) {
|
||||
await checkModifyPermission(ctx);
|
||||
});
|
||||
|
||||
async function checkModifyPermission(ctx) {
|
||||
const models = Self.app.models;
|
||||
const instance = ctx.instance;
|
||||
const userId = ctx.options.accessToken.userId;
|
||||
const user = await ctx.instance.userFk;
|
||||
const modifiedUser = await getUserToModify(null, user, models);
|
||||
|
||||
if (userId != modifiedUser.id && userId != modifiedUser.bossFk)
|
||||
throw new UserError('You dont have permission to modify this user');
|
||||
});
|
||||
let notificationFk;
|
||||
let workerId;
|
||||
|
||||
Self.remoteMethod('deleteNotification', {
|
||||
description: 'Deletes a notification subscription',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'ctx',
|
||||
type: 'object',
|
||||
http: {source: 'context'}
|
||||
},
|
||||
{
|
||||
arg: 'notificationId',
|
||||
type: 'number',
|
||||
required: true
|
||||
},
|
||||
],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
verb: 'POST',
|
||||
path: '/deleteNotification'
|
||||
if (instance) {
|
||||
notificationFk = instance.notificationFk;
|
||||
workerId = instance.userFk;
|
||||
} else {
|
||||
const notificationSubscription = await models.NotificationSubscription.findById(ctx.where.id);
|
||||
notificationFk = notificationSubscription.notificationFk;
|
||||
workerId = notificationSubscription.userFk;
|
||||
}
|
||||
});
|
||||
|
||||
Self.deleteNotification = async function(ctx, notificationId) {
|
||||
const models = Self.app.models;
|
||||
const user = ctx.req.accessToken.userId;
|
||||
const modifiedUser = await getUserToModify(notificationId, null, models);
|
||||
const worker = await models.Worker.findById(workerId, {fields: ['id', 'bossFk']});
|
||||
const available = await Self.getAvailable(workerId);
|
||||
const hasAcl = available.has(notificationFk);
|
||||
|
||||
if (user != modifiedUser.id && user != modifiedUser.bossFk)
|
||||
throw new UserError('You dont have permission to modify this user');
|
||||
|
||||
await models.NotificationSubscription.destroyById(notificationId);
|
||||
};
|
||||
|
||||
async function getUserToModify(notificationId, userFk, models) {
|
||||
let userToModify = userFk;
|
||||
if (notificationId) {
|
||||
const subscription = await models.NotificationSubscription.findById(notificationId);
|
||||
userToModify = subscription.userFk;
|
||||
}
|
||||
return await models.Worker.findOne({
|
||||
fields: ['id', 'bossFk'],
|
||||
where: {
|
||||
id: userToModify
|
||||
}
|
||||
});
|
||||
if (!hasAcl || (userId != worker.id && userId != worker.bossFk))
|
||||
throw new UserError('The notification subscription of this worker cant be modified');
|
||||
}
|
||||
|
||||
Self.getAvailable = async function(userId, options) {
|
||||
const availableNotificationsMap = new Map();
|
||||
const models = Self.app.models;
|
||||
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const roles = await models.RoleMapping.find({
|
||||
fields: ['roleId'],
|
||||
where: {principalId: userId}
|
||||
}, myOptions);
|
||||
|
||||
const availableNotifications = await models.NotificationAcl.find({
|
||||
fields: ['notificationFk', 'roleFk'],
|
||||
include: {relation: 'notification'},
|
||||
where: {
|
||||
roleFk: {
|
||||
inq: roles.map(role => role.roleId),
|
||||
},
|
||||
}
|
||||
}, myOptions);
|
||||
|
||||
for (available of availableNotifications) {
|
||||
availableNotificationsMap.set(available.notificationFk, {
|
||||
id: null,
|
||||
notificationFk: available.notificationFk,
|
||||
name: available.notification().name,
|
||||
description: available.notification().description,
|
||||
active: false
|
||||
});
|
||||
}
|
||||
return availableNotificationsMap;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('loopback model MailAliasAccount', () => {
|
||||
it('should fail to add a mail Alias if the worker doesnt have ACLs', async() => {
|
||||
const tx = await models.MailAliasAccount.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 57}};
|
||||
await models.MailAliasAccount.create({mailAlias: 2, account: 5}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('The alias cant be modified');
|
||||
});
|
||||
|
||||
it('should add a mail Alias', async() => {
|
||||
const tx = await models.MailAliasAccount.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 9}};
|
||||
await models.MailAliasAccount.create({mailAlias: 2, account: 5}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should add a mail Alias of an inherit role', async() => {
|
||||
const tx = await models.MailAliasAccount.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 9}};
|
||||
await models.MailAliasAccount.create({mailAlias: 3, account: 5}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete a mail Alias', async() => {
|
||||
const tx = await models.MailAliasAccount.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 1}};
|
||||
const mailAclId = 2;
|
||||
await models.MailAliasAccount.destroyAll({id: mailAclId}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,74 +1,126 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('loopback model NotificationSubscription', () => {
|
||||
it('Should fail to delete a notification if the user is not editing itself or a subordinate', async() => {
|
||||
it('should fail to add a notification subscription if the worker doesnt have ACLs', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const user = 9;
|
||||
const options = {transaction: tx, accessToken: {userId: 9}};
|
||||
await models.NotificationSubscription.create({notificationFk: 1, userFk: 62}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('The notification subscription of this worker cant be modified');
|
||||
});
|
||||
|
||||
it('should fail to add a notification subscription if the user isnt editing itself or subordinate', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 1}};
|
||||
await models.NotificationSubscription.create({notificationFk: 1, userFk: 9}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('The notification subscription of this worker cant be modified');
|
||||
});
|
||||
|
||||
it('should fail to delete a notification subscription if the user isnt editing itself or subordinate', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 9}};
|
||||
const notificationSubscriptionId = 2;
|
||||
const ctx = {req: {accessToken: {userId: user}}};
|
||||
const notification = await models.NotificationSubscription.findById(notificationSubscriptionId);
|
||||
await models.NotificationSubscription.destroyAll({id: notificationSubscriptionId}, options);
|
||||
|
||||
let error;
|
||||
|
||||
try {
|
||||
await models.NotificationSubscription.deleteNotification(ctx, notification.id, options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toContain('You dont have permission to modify this user');
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('The notification subscription of this worker cant be modified');
|
||||
});
|
||||
|
||||
it('Should delete a notification if the user is editing itself', async() => {
|
||||
it('should add a notification subscription if the user is editing itself', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const user = 9;
|
||||
const options = {transaction: tx, accessToken: {userId: 9}};
|
||||
await models.NotificationSubscription.create({notificationFk: 2, userFk: 9}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete a notification subscription if the user is editing itself', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 9}};
|
||||
const notificationSubscriptionId = 6;
|
||||
await models.NotificationSubscription.destroyAll({id: notificationSubscriptionId}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should add a notification subscription if the user is editing a subordinate', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 9}};
|
||||
await models.NotificationSubscription.create({notificationFk: 1, userFk: 5}, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete a notification subscription if the user is editing a subordinate', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx, accessToken: {userId: 19}};
|
||||
const notificationSubscriptionId = 4;
|
||||
const ctx = {req: {accessToken: {userId: user}}};
|
||||
const notification = await models.NotificationSubscription.findById(notificationSubscriptionId);
|
||||
await models.NotificationSubscription.destroyAll({id: notificationSubscriptionId}, options);
|
||||
|
||||
await models.NotificationSubscription.deleteNotification(ctx, notification.id, options);
|
||||
|
||||
const deletedNotification = await models.NotificationSubscription.findById(notificationSubscriptionId);
|
||||
|
||||
expect(deletedNotification).toBeNull();
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
error = e;
|
||||
}
|
||||
});
|
||||
|
||||
it('Should delete a notification if the user is editing a subordinate', async() => {
|
||||
const tx = await models.NotificationSubscription.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const user = 9;
|
||||
const notificationSubscriptionId = 5;
|
||||
const ctx = {req: {accessToken: {userId: user}}};
|
||||
const notification = await models.NotificationSubscription.findById(notificationSubscriptionId);
|
||||
|
||||
await models.NotificationSubscription.deleteNotification(ctx, notification.id, options);
|
||||
|
||||
const deletedNotification = await models.NotificationSubscription.findById(notificationSubscriptionId);
|
||||
|
||||
expect(deletedNotification).toBeNull();
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
},
|
||||
"darkMode": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"tabletFk": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
@ -43,6 +46,11 @@
|
|||
"type": "belongsTo",
|
||||
"model": "VnUser",
|
||||
"foreignKey": "userFk"
|
||||
}
|
||||
},
|
||||
"Tablet": {
|
||||
"type": "belongsTo",
|
||||
"model": "docuwareTablet",
|
||||
"foreignKey": "tabletFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/viaexpress-config/internationalExpedition')(Self);
|
||||
require('../methods/viaexpress-config/renderer')(Self);
|
||||
require('../methods/viaexpress-config/deleteExpedition')(Self);
|
||||
require('../methods/viaexpress-config/deleteExpeditionRenderer')(Self);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "VnRole",
|
||||
"base": "Role",
|
||||
"validateUpsert": true,
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "account.role"
|
||||
}
|
||||
},
|
||||
"mixins": {
|
||||
"Loggable": true
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ const vnModel = require('vn-loopback/common/models/vn-model');
|
|||
const {Email} = require('vn-print');
|
||||
const ForbiddenError = require('vn-loopback/util/forbiddenError');
|
||||
const LoopBackContext = require('loopback-context');
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = function(Self) {
|
||||
vnModel(Self);
|
||||
|
@ -9,7 +10,6 @@ module.exports = function(Self) {
|
|||
require('../methods/vn-user/sign-in')(Self);
|
||||
require('../methods/vn-user/acl')(Self);
|
||||
require('../methods/vn-user/recover-password')(Self);
|
||||
require('../methods/vn-user/validate-token')(Self);
|
||||
require('../methods/vn-user/privileges')(Self);
|
||||
require('../methods/vn-user/validate-auth')(Self);
|
||||
require('../methods/vn-user/renew-token')(Self);
|
||||
|
@ -92,7 +92,11 @@ module.exports = function(Self) {
|
|||
};
|
||||
|
||||
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 recoverHashes = {
|
||||
|
@ -108,7 +112,7 @@ module.exports = function(Self) {
|
|||
const params = {
|
||||
recipient: info.email,
|
||||
lang: user.lang,
|
||||
url: url.slice(0, -1) + recoverHash
|
||||
url: origin + '/#!' + recoverHash
|
||||
};
|
||||
|
||||
const options = Object.assign({}, info.options);
|
||||
|
@ -120,11 +124,43 @@ module.exports = function(Self) {
|
|||
return email.send();
|
||||
});
|
||||
|
||||
Self.validateLogin = async function(user, password) {
|
||||
let loginInfo = Object.assign({password}, Self.userUses(user));
|
||||
token = await Self.login(loginInfo, 'user');
|
||||
/**
|
||||
* Sign-in validate
|
||||
* @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();
|
||||
|
||||
if (ctx)
|
||||
await Self.signInValidate(user, userToken, token, ctx);
|
||||
|
||||
try {
|
||||
await Self.app.models.Account.sync(userToken.name, password);
|
||||
} 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
|
||||
.filter(acl => acl.property != 'changePassword');
|
||||
Self.sharedClass._methods.find(method => method.name == 'changePassword').ctor.settings.acls
|
||||
.filter(acl => acl.property != 'changePassword');
|
||||
|
||||
Self.userSecurity = async(ctx, userId, options) => {
|
||||
const models = Self.app.models;
|
||||
|
@ -212,23 +248,30 @@ module.exports = function(Self) {
|
|||
|
||||
const env = process.env.NODE_ENV;
|
||||
const liliumUrl = await Self.app.models.Url.findOne({
|
||||
where: {and: [
|
||||
{appName: 'lilium'},
|
||||
{environment: env}
|
||||
]}
|
||||
where: {
|
||||
and: [
|
||||
{appName: 'lilium'},
|
||||
{environment: env}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
class Mailer {
|
||||
async send(verifyOptions, cb) {
|
||||
const params = {
|
||||
url: verifyOptions.verifyHref,
|
||||
recipient: verifyOptions.to
|
||||
};
|
||||
try {
|
||||
const url = new URL(verifyOptions.verifyHref);
|
||||
if (process.env.NODE_ENV) url.port = '';
|
||||
|
||||
const email = new Email('email-verify', params);
|
||||
email.send();
|
||||
const email = new Email('email-verify', {
|
||||
url: url.href,
|
||||
recipient: verifyOptions.to
|
||||
});
|
||||
await email.send();
|
||||
|
||||
cb(null, verifyOptions.to);
|
||||
cb(null, verifyOptions.to);
|
||||
} catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
"table": "account.user"
|
||||
}
|
||||
},
|
||||
"mixins": {
|
||||
"Loggable": true
|
||||
},
|
||||
"resetPasswordTokenTTL": "604800",
|
||||
"properties": {
|
||||
"id": {
|
||||
|
@ -63,7 +66,7 @@
|
|||
"relations": {
|
||||
"role": {
|
||||
"type": "belongsTo",
|
||||
"model": "Role",
|
||||
"model": "VnRole",
|
||||
"foreignKey": "roleFk"
|
||||
},
|
||||
"roles": {
|
||||
|
@ -95,34 +98,30 @@
|
|||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"property": "recoverPassword",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"property": "validateToken",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"property": "validateAuth",
|
||||
}, {
|
||||
"property": "recoverPassword",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
}, {
|
||||
"property": "validateAuth",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}, {
|
||||
"property": "privileges",
|
||||
"accessType": "*",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW"
|
||||
}, {
|
||||
"property": "renewToken",
|
||||
"accessType": "WRITE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
],
|
||||
"scopes": {
|
||||
|
|
|
@ -7,6 +7,10 @@ process.on('warning', warning => {
|
|||
console.log(warning.stack);
|
||||
});
|
||||
|
||||
process.on('SIGUSR2', async() => {
|
||||
if (container) await container.rm();
|
||||
});
|
||||
|
||||
process.on('exit', async function() {
|
||||
if (container) await container.rm();
|
||||
});
|
||||
|
@ -55,8 +59,8 @@ async function test() {
|
|||
const JunitReporter = require('jasmine-reporters');
|
||||
jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
|
||||
|
||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
|
||||
jasmine.exitOnCompletion = true;
|
||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 900000;
|
||||
}
|
||||
|
||||
const backSpecs = [
|
||||
|
|
|
@ -74,7 +74,7 @@ BEGIN
|
|||
clientFk,
|
||||
dued,
|
||||
companyFk,
|
||||
cplusInvoiceType477Fk
|
||||
siiTypeInvoiceOutFk
|
||||
)
|
||||
SELECT
|
||||
1,
|
||||
|
@ -118,13 +118,13 @@ BEGIN
|
|||
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
||||
FROM tmp.ticketToInvoice ti;
|
||||
|
||||
CALL invoiceExpenceMake(vNewInvoiceId);
|
||||
CALL invoiceExpenseMake(vNewInvoiceId);
|
||||
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
||||
|
||||
UPDATE invoiceOut io
|
||||
JOIN (
|
||||
SELECT SUM(amount) AS total
|
||||
FROM invoiceOutExpence
|
||||
FROM invoiceOutExpense
|
||||
WHERE invoiceOutFk = vNewInvoiceId
|
||||
) base
|
||||
JOIN (
|
||||
|
@ -166,18 +166,18 @@ BEGIN
|
|||
SET @vTaxableBaseServices := 0.00;
|
||||
SET @vTaxCodeGeneral := NULL;
|
||||
|
||||
INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInId, @vTaxableBaseServices, sub.expenceFk, sub.taxTypeSageFk , sub.transactionTypeSageFk
|
||||
INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInId, @vTaxableBaseServices, sub.expenseFk, sub.taxTypeSageFk , sub.transactionTypeSageFk
|
||||
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
|
||||
JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code
|
||||
WHERE i.isService
|
||||
HAVING taxableBase
|
||||
) sub;
|
||||
|
||||
INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInId, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, @vTaxableBaseServices, 0) taxableBase, i.expenceFk, i.taxTypeSageFk , i.transactionTypeSageFk
|
||||
INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInId, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, @vTaxableBaseServices, 0) taxableBase, i.expenseFk, i.taxTypeSageFk , i.transactionTypeSageFk
|
||||
FROM tmp.ticketTax tt
|
||||
JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code
|
||||
WHERE !i.isService
|
||||
|
|
|
@ -96,7 +96,7 @@ BEGIN
|
|||
clientFk,
|
||||
dued,
|
||||
companyFk,
|
||||
cplusInvoiceType477Fk
|
||||
siiTypeInvoiceOutFk
|
||||
)
|
||||
SELECT
|
||||
1,
|
||||
|
@ -139,13 +139,13 @@ BEGIN
|
|||
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
||||
FROM tmp.ticketToInvoice ti;
|
||||
|
||||
CALL invoiceExpenceMake(vNewInvoiceId);
|
||||
CALL invoiceExpenseMake(vNewInvoiceId);
|
||||
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
||||
|
||||
UPDATE invoiceOut io
|
||||
JOIN (
|
||||
SELECT SUM(amount) total
|
||||
FROM invoiceOutExpence
|
||||
FROM invoiceOutExpense
|
||||
WHERE invoiceOutFk = vNewInvoiceId
|
||||
) base
|
||||
JOIN (
|
||||
|
@ -182,15 +182,15 @@ BEGIN
|
|||
SET @vTaxableBaseServices := 0.00;
|
||||
SET @vTaxCodeGeneral := NULL;
|
||||
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInFk,
|
||||
@vTaxableBaseServices,
|
||||
sub.expenceFk,
|
||||
sub.expenseFk,
|
||||
sub.taxTypeSageFk,
|
||||
sub.transactionTypeSageFk
|
||||
FROM (
|
||||
SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase,
|
||||
i.expenceFk,
|
||||
i.expenseFk,
|
||||
i.taxTypeSageFk,
|
||||
i.transactionTypeSageFk,
|
||||
@vTaxCodeGeneral := i.taxClassCodeFk
|
||||
|
@ -200,11 +200,11 @@ BEGIN
|
|||
HAVING taxableBase
|
||||
) sub;
|
||||
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInFk,
|
||||
SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral,
|
||||
@vTaxableBaseServices, 0) taxableBase,
|
||||
i.expenceFk,
|
||||
i.expenseFk,
|
||||
i.taxTypeSageFk ,
|
||||
i.transactionTypeSageFk
|
||||
FROM tmp.ticketTax tt
|
||||
|
|
|
@ -96,7 +96,7 @@ BEGIN
|
|||
clientFk,
|
||||
dued,
|
||||
companyFk,
|
||||
cplusInvoiceType477Fk
|
||||
siiTypeInvoiceOutFk
|
||||
)
|
||||
SELECT
|
||||
1,
|
||||
|
@ -135,13 +135,13 @@ BEGIN
|
|||
INSERT INTO ticketTracking(stateFk,ticketFk,workerFk)
|
||||
SELECT * FROM tmp.updateInter;
|
||||
|
||||
CALL invoiceExpenceMake(vNewInvoiceId);
|
||||
CALL invoiceExpenseMake(vNewInvoiceId);
|
||||
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
||||
|
||||
UPDATE invoiceOut io
|
||||
JOIN (
|
||||
SELECT SUM(amount) total
|
||||
FROM invoiceOutExpence
|
||||
FROM invoiceOutExpense
|
||||
WHERE invoiceOutFk = vNewInvoiceId
|
||||
) base
|
||||
JOIN (
|
||||
|
@ -178,15 +178,15 @@ BEGIN
|
|||
SET @vTaxableBaseServices := 0.00;
|
||||
SET @vTaxCodeGeneral := NULL;
|
||||
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInFk,
|
||||
@vTaxableBaseServices,
|
||||
sub.expenceFk,
|
||||
sub.expenseFk,
|
||||
sub.taxTypeSageFk,
|
||||
sub.transactionTypeSageFk
|
||||
FROM (
|
||||
SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase,
|
||||
i.expenceFk,
|
||||
i.expenseFk,
|
||||
i.taxTypeSageFk,
|
||||
i.transactionTypeSageFk,
|
||||
@vTaxCodeGeneral := i.taxClassCodeFk
|
||||
|
@ -196,11 +196,11 @@ BEGIN
|
|||
HAVING taxableBase
|
||||
) sub;
|
||||
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenseFk, taxTypeSageFk, transactionTypeSageFk)
|
||||
SELECT vNewInvoiceInFk,
|
||||
SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral,
|
||||
@vTaxableBaseServices, 0) taxableBase,
|
||||
i.expenceFk,
|
||||
i.expenseFk,
|
||||
i.taxTypeSageFk ,
|
||||
i.transactionTypeSageFk
|
||||
FROM tmp.ticketTax tt
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM mariadb:10.7.7
|
||||
FROM mariadb:10.11.6
|
||||
|
||||
ENV MYSQL_ROOT_PASSWORD root
|
||||
ENV TZ Europe/Madrid
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
CREATE SCHEMA IF NOT EXISTS `vn2008`;
|
||||
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`awbVolume`
|
||||
|
|
|
@ -2,11 +2,3 @@ UPDATE `salix`.`ACL`
|
|||
SET `property` = 'state',
|
||||
`model` = 'Ticket'
|
||||
WHERE `property` = 'changeState';
|
||||
|
||||
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'productionboss'@;
|
||||
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'productionAssi'@;
|
||||
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'hr'@;
|
||||
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'salesPerson'@;
|
||||
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'deliveryPerson'@;
|
||||
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'employee'@;
|
||||
REVOKE EXECUTE ON `vn`.`ticket_setState` FROM 'employee'@;
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
-- Place your SQL code here
|
||||
|
||||
ALTER TABLE `vn`.`productionConfig` ADD shortageAddressFk int(11) COMMENT 'Consignatario por defecto para añadir un item de alta';
|
||||
ALTER TABLE `vn`.`productionConfig` ADD CONSTRAINT productionConfig_FK FOREIGN KEY (shortageAddressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE `vn`.`sale` MODIFY COLUMN originalQuantity double(9,1) DEFAULT NULL NULL COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity';
|
||||
|
||||
INSERT INTO `salix`.`ACL` ( model, property, accessType, permission, principalType, principalId) VALUES( 'AddressShortage', '*', 'READ', 'ALLOW', 'ROLE', 'production');
|
||||
|
||||
-- vn.addressShortage definition
|
||||
|
||||
CREATE TABLE `vn`.`addressShortage` (
|
||||
`addressFk` int(11) NOT NULL,
|
||||
PRIMARY KEY (`addressFk`),
|
||||
CONSTRAINT `addressShortage_FK` FOREIGN KEY (`addressFk`) REFERENCES `address` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_setVisibleDiscard`(
|
||||
vItemFk INT,
|
||||
vWarehouseFk INT,
|
||||
vQuantity INT,
|
||||
vAddressFk INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Procedimiento para dar dar de baja/alta un item, si vAddressFk es NULL se entiende que se da de alta y se toma el addressFk de la configuración
|
||||
*
|
||||
* @param vItemFk Identificador del ítem
|
||||
* @param vWarehouseFk id del warehouse
|
||||
* @param vQuantity a dar de alta/baja
|
||||
* @param vAddressFk id address
|
||||
*/
|
||||
DECLARE vTicketFk INT;
|
||||
DECLARE vClientFk INT;
|
||||
DECLARE vDefaultCompanyFk INT;
|
||||
DECLARE vCalc INT;
|
||||
DECLARE vAddressShortage INT;
|
||||
|
||||
SELECT barcodeToItem(vItemFk) INTO vItemFk;
|
||||
|
||||
SELECT DEFAULT(companyFk) INTO vDefaultCompanyFk
|
||||
FROM vn.ticket LIMIT 1;
|
||||
|
||||
IF vAddressFk IS NULL THEN
|
||||
SELECT pc.shortageAddressFk INTO vAddressShortage
|
||||
FROM productionConfig pc ;
|
||||
ELSE
|
||||
SET vAddressShortage = vAddressFk;
|
||||
END IF;
|
||||
|
||||
SELECT a.clientFk INTO vClientFk
|
||||
FROM address a
|
||||
WHERE a.id = vAddressFk;
|
||||
|
||||
SELECT t.id INTO vTicketFk
|
||||
FROM ticket t
|
||||
JOIN address a ON a.id = t.addressFk
|
||||
JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
WHERE t.warehouseFk = vWarehouseFk
|
||||
AND a.id = vAddressShortage
|
||||
AND DATE(t.shipped) = util.VN_CURDATE()
|
||||
AND ts.code = 'DELIVERED'
|
||||
LIMIT 1;
|
||||
|
||||
CALL cache.visible_refresh(vCalc, TRUE, vWarehouseFk);
|
||||
|
||||
IF vTicketFk IS NULL THEN
|
||||
CALL ticket_add(
|
||||
vClientFk,
|
||||
util.VN_CURDATE(),
|
||||
vWarehouseFk,
|
||||
vDefaultCompanyFk,
|
||||
vAddressFk,
|
||||
NULL,
|
||||
NULL,
|
||||
util.VN_CURDATE(),
|
||||
account.myUser_getId(),
|
||||
FALSE,
|
||||
vTicketFk);
|
||||
END IF;
|
||||
|
||||
INSERT INTO sale(ticketFk, itemFk, concept, quantity)
|
||||
SELECT vTicketFk,
|
||||
vItemFk,
|
||||
CONCAT(longName,' ', worker_getCode(), ' ', LEFT(CAST(util.VN_NOW() AS TIME),5)),
|
||||
vQuantity
|
||||
FROM item
|
||||
WHERE id = vItemFk;
|
||||
|
||||
UPDATE cache.visible
|
||||
SET visible = visible - vQuantity
|
||||
WHERE calc_id = vCalc
|
||||
AND item_id = vItemFk;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -21,11 +21,11 @@ DELETE FROM `salix`.`ACL`
|
|||
'getSummary'
|
||||
);
|
||||
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`)
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
|
||||
VALUES ('Claim','filter','READ','ALLOW','ROLE','claimViewer');
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`)
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
|
||||
VALUES ('Claim','find','READ','ALLOW','ROLE','claimViewer');
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`)
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
|
||||
VALUES ('Claim','findById','READ','ALLOW','ROLE','claimViewer');
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`)
|
||||
VALUES ('Claim','getSummary','READ','ALLOW','ROLE','claimViewer');
|
||||
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
|
||||
VALUES ('Claim','getSummary','READ','ALLOW','ROLE','claimViewer');
|
|
@ -0,0 +1,95 @@
|
|||
ALTER TABLE `vn`.`client` MODIFY COLUMN `credit` decimal(10,2) unsigned DEFAULT 0.00 NOT NULL;
|
||||
|
||||
DELETE FROM `salix`.`ACL` WHERE `model` = 'Client' AND `property` = 'create';
|
||||
|
||||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_beforeUpdate`
|
||||
BEFORE UPDATE ON `client`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vText VARCHAR(255) DEFAULT NULL;
|
||||
DECLARE vPayMethodFk INT;
|
||||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF NOT(NEW.credit <=> OLD.credit) THEN
|
||||
INSERT INTO clientCredit
|
||||
SET clientFk = NEW.id,
|
||||
amount = NEW.credit,
|
||||
workerFk = NEW.editorFk;
|
||||
END IF;
|
||||
-- Comprueba que el formato de los teléfonos es válido
|
||||
|
||||
IF !(NEW.phone <=> OLD.phone) AND (NEW.phone <> '') THEN
|
||||
CALL pbx.phone_isValid(NEW.phone);
|
||||
END IF;
|
||||
|
||||
IF !(NEW.mobile <=> OLD.mobile) AND (NEW.mobile <> '')THEN
|
||||
CALL pbx.phone_isValid(NEW.mobile);
|
||||
END IF;
|
||||
|
||||
SELECT id INTO vPayMethodFk
|
||||
FROM vn.payMethod
|
||||
WHERE code = 'bankDraft';
|
||||
|
||||
IF NEW.payMethodFk = vPayMethodFk AND NEW.dueDay = 0 THEN
|
||||
SET NEW.dueDay = 5;
|
||||
END IF;
|
||||
|
||||
-- Avisar al comercial si ha llegado la documentación sepa/core
|
||||
|
||||
IF NEW.hasSepaVnl AND !OLD.hasSepaVnl THEN
|
||||
SET vText = 'Sepa de VNL';
|
||||
END IF;
|
||||
|
||||
IF NEW.hasCoreVnl AND !OLD.hasCoreVnl THEN
|
||||
SET vText = 'Core de VNL';
|
||||
END IF;
|
||||
|
||||
IF vText IS NOT NULL
|
||||
THEN
|
||||
INSERT INTO mail(receiver, replyTo, `subject`, body)
|
||||
SELECT
|
||||
CONCAT(IF(ac.id,u.name, 'jgallego'), '@verdnatura.es'),
|
||||
'administracion@verdnatura.es',
|
||||
CONCAT('Cliente ', NEW.id),
|
||||
CONCAT('Recibida la documentación: ', vText)
|
||||
FROM worker w
|
||||
LEFT JOIN account.user u ON w.id = u.id AND u.active
|
||||
LEFT JOIN account.account ac ON ac.id = u.id
|
||||
WHERE w.id = NEW.salesPersonFk;
|
||||
END IF;
|
||||
|
||||
IF NEW.salespersonFk IS NULL AND OLD.salespersonFk IS NOT NULL THEN
|
||||
IF (SELECT COUNT(clientFk)
|
||||
FROM clientProtected
|
||||
WHERE clientFk = NEW.id
|
||||
) > 0 THEN
|
||||
CALL util.throw("HAS_CLIENT_PROTECTED");
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
IF !(NEW.salesPersonFk <=> OLD.salesPersonFk) THEN
|
||||
SET NEW.lastSalesPersonFk = IFNULL(NEW.salesPersonFk, OLD.salesPersonFk);
|
||||
END IF;
|
||||
|
||||
IF !(NEW.businessTypeFk <=> OLD.businessTypeFk) AND (NEW.businessTypeFk = 'individual' OR OLD.businessTypeFk = 'individual') THEN
|
||||
SET NEW.isTaxDataChecked = 0;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_AfterInsert`
|
||||
AFTER INSERT ON `client`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
IF NEW.credit IS NOT NULL AND NEW.credit THEN
|
||||
INSERT INTO clientCredit
|
||||
SET clientFk = NEW.id,
|
||||
workerFk = NEW.editorFk,
|
||||
amount = NEW.credit;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||
VALUES
|
||||
('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('CplusInvoiceType477', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('SiiTypeInvoiceOut', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative');
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
-- Auto-generated SQL script #202311061003
|
||||
UPDATE salix.accessTokenConfig
|
||||
SET courtesyTime=60
|
||||
WHERE id=1;
|
|
@ -0,0 +1 @@
|
|||
CALL `account`.`role_sync`();
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE account.sambaConfig
|
||||
ADD userDn varchar(255) NOT NULL COMMENT 'Base DN for users without domain DN part';
|
|
@ -0,0 +1,4 @@
|
|||
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||
VALUES
|
||||
('Application', 'executeProc', '*', 'ALLOW', 'ROLE', 'employee'),
|
||||
('Application', 'executeFunc', '*', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,3 @@
|
|||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES
|
||||
('NotificationSubscription', 'getList', 'READ', 'ALLOW', 'ROLE', 'employee');
|
|
@ -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 ;
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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');
|
|
@ -0,0 +1,6 @@
|
|||
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) VALUES
|
||||
('VnRole','*','READ','ALLOW','ROLE','employee'),
|
||||
('VnRole','*','WRITE','ALLOW','ROLE','it');
|
||||
|
||||
DELETE FROM`salix`.`ACL` WHERE model='Role';
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `vn`.`ticketTracking` CHANGE `workerFk` `userFk` int(10) unsigned DEFAULT NULL NULL;
|
|
@ -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;
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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`());
|
|
@ -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';
|
|
@ -0,0 +1,8 @@
|
|||
-- Definición de la tabla mailAliasACL
|
||||
|
||||
CREATE OR REPLACE TABLE `account`.`mailAliasAcl` (
|
||||
`mailAliasFk` int(10) unsigned NOT NULL,
|
||||
`roleFk` int(10) unsigned NOT NULL,
|
||||
FOREIGN KEY (`mailAliasFk`) REFERENCES `account`.`mailAlias` (`id`),
|
||||
FOREIGN KEY (`roleFk`) REFERENCES `account`.`role` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
@ -0,0 +1,7 @@
|
|||
ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `cplusInvoiceTyoeFk`;
|
||||
ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `invoiceCorrectionType_Fk33`;
|
||||
ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `invoiceCorrection_ibfk_1`;
|
||||
|
||||
ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `siiTypeInvoiceOut_FK` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `vn`.`siiTypeInvoiceOut`(id) ON UPDATE CASCADE;
|
||||
ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `invoiceCorrectionType_FK` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `vn`.`invoiceCorrectionType`(id) ON UPDATE CASCADE;
|
||||
ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `cplusRectificationType_FK` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `vn`.`cplusRectificationType`(id) ON UPDATE CASCADE;
|
|
@ -0,0 +1,33 @@
|
|||
DELIMITER $$
|
||||
$$
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`getTaxBases`()
|
||||
BEGIN
|
||||
/**
|
||||
* Calcula y devuelve en número de bases imponibles postivas y negativas
|
||||
* Requiere la tabla temporal tmp.ticketToInvoice(id)
|
||||
*
|
||||
* returns tmp.taxBases
|
||||
*/
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
|
||||
(KEY (ticketFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT id ticketFk
|
||||
FROM tmp.ticketToInvoice;
|
||||
|
||||
CALL ticket_getTax(NULL);
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.taxBases;
|
||||
CREATE TEMPORARY TABLE tmp.taxBases
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
SUM(taxableBase > 0) as positive,
|
||||
SUM(taxableBase < 0) as negative
|
||||
FROM(
|
||||
SELECT SUM(taxableBase) taxableBase
|
||||
FROM tmp.ticketTax
|
||||
GROUP BY pgcFk
|
||||
) t;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -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);
|
|
@ -0,0 +1,9 @@
|
|||
ALTER TABLE `vn`.`clientSms` ADD `ticketFk` int(11) NULL;
|
||||
ALTER TABLE `vn`.`clientSms` ADD CONSTRAINT `clientSms_FK_2` FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
INSERT INTO`vn`.`clientSms` (`clientFk`, `smsFk`, `ticketFk`)
|
||||
SELECT `t`.`clientFk`, `s`.`smsFk`, `s`.`ticketFk`
|
||||
FROM `vn`.`clientSms` `s`
|
||||
JOIN `vn`.`ticket` `t` ON `t`.`id` = `s`.`ticketFk`;
|
||||
|
||||
RENAME TABLE `vn`.`ticketSms` TO `vn`.`ticketSms__`;
|
|
@ -0,0 +1,17 @@
|
|||
DELETE FROM `salix`.`ACL`
|
||||
WHERE model = 'VnUser'
|
||||
AND property = 'renewToken';
|
||||
|
||||
INSERT INTO `account`.`role` (name, description)
|
||||
VALUES ('timeControl','Tablet para fichar');
|
||||
|
||||
INSERT INTO `account`.`roleInherit` (role, inheritsFrom)
|
||||
VALUES (127, 11);
|
||||
|
||||
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||
VALUES
|
||||
('WorkerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', 'timeControl'),
|
||||
('WorkerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', 'timeControl'),
|
||||
('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl');
|
||||
|
||||
CALL `account`.`role_sync`();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue