Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4074-download-user-ACL
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Alexandre Riera 2023-06-12 07:46:49 +02:00
commit 0a491c6b62
495 changed files with 23268 additions and 23273 deletions

View File

@ -1,6 +1,6 @@
extends: [eslint:recommended, google, plugin:jasmine/recommended] extends: [eslint:recommended, google, plugin:jasmine/recommended]
parserOptions: parserOptions:
ecmaVersion: 2018 ecmaVersion: 2020
sourceType: "module" sourceType: "module"
plugins: plugins:
- jasmine - jasmine

View File

@ -5,17 +5,78 @@ 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).
## [2316.01] - 2023-05-04 ## [2326.01] - 2023-06-29
### Added
### Changed
### Fixed
-
## [2324.01] - 2023-06-08
### Added
- (Tickets -> Abono) Al abonar permite crear el ticket abono con almacén o sin almmacén
- (General -> Desplegables) Mejorada eficiencia de carga de datos
- (General -> Históricos) Ahora, ademas de los ids, se muestra la descripión de los atributos
- (General -> Históricos) Botón para hacer más ágil mostrar sólo los cambios en un registro
- (General -> Históricos) Filtro por cambios
### Changed
- (General -> Permisos) Mejorada seguridad
- (General -> Históricos) Elementos de la interfaz reorganizados para hacerla más ágil e intuitiva
### Fixed
-
## [2322.01] - 2023-06-01
### Added
- (Tickets -> Crear Factura) Al facturar se envia automáticamente el pdf al cliente
- (Artículos -> Histórico) Filtro para mostrar lo anterior al inventario
- (Trabajadores -> Nuevo trabajador) Permite elegir el método de pago
### Changed
- (Trabajadores -> Nuevo trabajador) Los clientes se crean sin 'TR' pero se añade tipo de negocio 'Trabajador'
### Fixed
- (Tickets -> Líneas) Se permite hacer split de líneas al mismo ticket
- (Tickets -> Cambiar estado) Ahora muestra la lista completa de todos los estados
## [2320.01] - 2023-05-25
### Added
- (Tickets -> Crear Factura) Al facturar se envia automáticamente el pdf al cliente
### Changed
- (Trabajadores -> Nuevo trabajador) Los clientes se crean sin 'TR' pero se añade tipo de negocio 'Trabajador'
### Fixed
-
## [2318.01] - 2023-05-08
### Added ### Added
- (Usuarios -> Histórico) Nueva sección - (Usuarios -> Histórico) Nueva sección
- (Roles -> Histórico) Nueva sección - (Roles -> Histórico) Nueva sección
- (Trabajadores -> Dar de alta) Permite elegir el método de pago
### Changed ### Changed
- (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral - (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral
- (Trabajadores -> Dar de alta) Quitada obligatoriedad del iban
### Fixed ### Fixed
- - (Ticket -> Boxing) Arreglado selección de horas
- (Cesta -> Índice) Optimizada búsqueda
## [2314.01] - 2023-04-20 ## [2314.01] - 2023-04-20

View File

@ -11,9 +11,9 @@ RUN apt-get update \
ca-certificates \ ca-certificates \
gnupg2 \ gnupg2 \
graphicsmagick \ graphicsmagick \
&& curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \ && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \ && apt-get install -y --no-install-recommends nodejs \
&& npm install -g npm@8.19.2 && npm install -g npm@9.6.6
# Puppeteer # Puppeteer

8
Jenkinsfile vendored
View File

@ -39,7 +39,7 @@ pipeline {
NODE_ENV = "" NODE_ENV = ""
} }
steps { steps {
nodejs('node-v14') { nodejs('node-v20') {
sh 'npm install --no-audit --prefer-offline' sh 'npm install --no-audit --prefer-offline'
sh 'gulp install --ci' sh 'gulp install --ci'
} }
@ -57,14 +57,14 @@ pipeline {
parallel { parallel {
stage('Frontend') { stage('Frontend') {
steps { steps {
nodejs('node-v14') { nodejs('node-v20') {
sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2'
} }
} }
} }
stage('Backend') { stage('Backend') {
steps { steps {
nodejs('node-v14') { nodejs('node-v20') {
sh 'npm run test:back:ci' sh 'npm run test:back:ci'
} }
} }
@ -80,7 +80,7 @@ pipeline {
CREDENTIALS = credentials('docker-registry') CREDENTIALS = credentials('docker-registry')
} }
steps { steps {
nodejs('node-v14') { nodejs('node-v20') {
sh 'gulp build' sh 'gulp build'
} }

View File

@ -1,17 +0,0 @@
name: cuenta
columns:
id: id
name: nombre
roleFk: rol
nickname: apodo
lang: idioma
password: contraseña
bcryptPassword: contraseña bcrypt
active: activo
email: email
emailVerified: email verificado
created: creado
updated: actualizado
image: imagen
hasGrant: tiene permiso
userFk: usuario

View File

@ -30,11 +30,11 @@ module.exports = Self => {
Self.newCollection = async(ctx, collectionFk, sectorFk, vWagons) => { Self.newCollection = async(ctx, collectionFk, sectorFk, vWagons) => {
let query = ''; let query = '';
const userId = ctx.req.accessToken.userId;
if (!collectionFk) { if (!collectionFk) {
const userId = ctx.req.accessToken.userId;
query = `CALL vn.collectionTrain_newBeta(?,?,?)`; query = `CALL vn.collectionTrain_newBeta(?,?,?)`;
const [result] = await Self.rawSql(query, [sectorFk, vWagons, userId]); const [result] = await Self.rawSql(query, [sectorFk, vWagons, userId], {userId});
if (result.length == 0) if (result.length == 0)
throw new Error(`No collections for today`); throw new Error(`No collections for today`);
@ -42,16 +42,16 @@ module.exports = Self => {
} }
query = `CALL vn.collectionTicket_get(?)`; query = `CALL vn.collectionTicket_get(?)`;
const [tickets] = await Self.rawSql(query, [collectionFk]); const [tickets] = await Self.rawSql(query, [collectionFk], {userId});
query = `CALL vn.collectionSale_get(?)`; query = `CALL vn.collectionSale_get(?)`;
const [sales] = await Self.rawSql(query, [collectionFk]); const [sales] = await Self.rawSql(query, [collectionFk], {userId});
query = `CALL vn.collectionPlacement_get(?)`; query = `CALL vn.collectionPlacement_get(?)`;
const [placements] = await Self.rawSql(query, [collectionFk]); const [placements] = await Self.rawSql(query, [collectionFk], {userId});
query = `CALL vn.collectionSticker_print(?,?)`; query = `CALL vn.collectionSticker_print(?,?)`;
await Self.rawSql(query, [collectionFk, sectorFk]); await Self.rawSql(query, [collectionFk, sectorFk], {userId});
return makeCollection(tickets, sales, placements, collectionFk); return makeCollection(tickets, sales, placements, collectionFk);
}; };

View File

@ -4,25 +4,25 @@ module.exports = Self => {
Self.remoteMethodCtx('deliveryNoteEmail', { Self.remoteMethodCtx('deliveryNoteEmail', {
description: 'Sends the delivery note email with an docuware attached PDF', description: 'Sends the delivery note email with an docuware attached PDF',
accessType: 'WRITE', accessType: 'WRITE',
accessScopes: ['docuwareDeliveryNoteEmail'],
accepts: [ accepts: [
{ {
arg: 'id', arg: 'id',
type: 'string', type: 'number',
required: true, required: true,
description: 'The ticket id', description: 'The ticket id',
http: {source: 'path'}
},
{
arg: 'recipient',
type: 'string',
description: 'The recipient email',
required: true,
}, },
{ {
arg: 'recipientId', arg: 'recipientId',
type: 'number', type: 'number',
description: 'The client id', description: 'The client id',
required: false required: true
},
{
arg: 'recipient',
type: 'string',
description: 'The recipient email',
required: false,
} }
], ],
returns: [ returns: [
@ -41,12 +41,13 @@ module.exports = Self => {
} }
], ],
http: { http: {
path: '/:id/delivery-note-email', path: '/delivery-note-email',
verb: 'POST' verb: 'POST'
} }
}); });
Self.deliveryNoteEmail = async(ctx, id) => { Self.deliveryNoteEmail = async(ctx, id, recipientId, recipient) => {
const models = Self.app.models;
const args = Object.assign({}, ctx.args); const args = Object.assign({}, ctx.args);
const params = { const params = {
recipient: args.recipient, recipient: args.recipient,
@ -57,9 +58,14 @@ module.exports = Self => {
for (const param in args) for (const param in args)
params[param] = args[param]; params[param] = args[param];
if (!recipient) {
client = await models.Client.findById(recipientId, {fields: ['email']});
params.recipient = client.email;
}
const email = new Email('delivery-note', params); const email = new Email('delivery-note', params);
const docuwareFile = await Self.app.models.Docuware.download(ctx, id, 'deliveryNote'); const docuwareFile = await models.Docuware.download(ctx, id, 'deliveryNote');
return email.send({ return email.send({
overrideAttachments: true, overrideAttachments: true,

View File

@ -1,9 +1,9 @@
LOAD DATA LOCAL INFILE ? LOAD DATA LOCAL INFILE ?
INTO TABLE `edi`.`item` INTO TABLE `edi`.`item`
CHARACTER SET ascii
FIELDS TERMINATED BY ';' FIELDS TERMINATED BY ';'
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12) LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12)
SET SET id = @col2,
id = @col2,
product_name = @col4, product_name = @col4,
name = @col5, name = @col5,
plant_id = @col7, plant_id = @col7,
@ -11,3 +11,4 @@ LOAD DATA LOCAL INFILE ?
entry_date = STR_TO_DATE(@col10, '%Y%m%d'), entry_date = STR_TO_DATE(@col10, '%Y%m%d'),
expiry_date = IFNULL(NULL,STR_TO_DATE(@col11, '%Y%m%d')), expiry_date = IFNULL(NULL,STR_TO_DATE(@col11, '%Y%m%d')),
change_date_time = STR_TO_DATE(@col12, '%Y%m%d%H%i') change_date_time = STR_TO_DATE(@col12, '%Y%m%d%H%i')

View File

@ -16,14 +16,14 @@ module.exports = Self => {
} }
}); });
Self.updateData = async() => { Self.updateData = async ctx => {
const models = Self.app.models; const models = Self.app.models;
// Get files checksum // Get files checksum
const tx = await Self.beginTransaction({}); const tx = await Self.beginTransaction({});
try { try {
const options = {transaction: tx}; const options = {transaction: tx, userId: ctx.req.accessToken.userId};
const files = await Self.rawSql('SELECT name, checksum, keyValue FROM edi.fileConfig', null, options); const files = await Self.rawSql('SELECT name, checksum, keyValue FROM edi.fileConfig', null, options);
const updatableFiles = []; const updatableFiles = [];
@ -121,7 +121,8 @@ module.exports = Self => {
host: ftpConfig.host, host: ftpConfig.host,
username: ftpConfig.user, username: ftpConfig.user,
password: ftpConfig.password, password: ftpConfig.password,
procotol: 'ftp' procotol: 'ftp',
additionalLftpCommands: 'set ssl:verify-certificate no'
}); });
} }
@ -132,7 +133,7 @@ module.exports = Self => {
const ftpClient = await getFtpClient(); const ftpClient = await getFtpClient();
console.debug(`Checking checksum for file ${file.name}...`); console.debug(`Checking checksum for file ${file.name}...`);
ftpClient.cat(`codes/${file.name}.txt`); ftpClient.cat(`codes/${file.name}.TXT`);
const response = await new Promise((resolve, reject) => { const response = await new Promise((resolve, reject) => {
ftpClient.exec((err, response) => { ftpClient.exec((err, response) => {

View File

@ -67,7 +67,7 @@ module.exports = Self => {
if (!image) return false; if (!image) return false;
const hasReadRole = models.ImageCollection.hasReadRole(ctx, collection); const hasReadRole = await models.ImageCollection.hasReadRole(ctx, collection);
if (!hasReadRole) if (!hasReadRole)
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);

View File

@ -23,13 +23,7 @@ module.exports = Self => {
let models = Self.app.models; let models = Self.app.models;
let user = await Self.findById(userId, { let user = await Self.findById(userId, {
fields: ['id', 'name', 'nickname', 'email', 'lang'], fields: ['id', 'name', 'nickname', 'email', 'lang']
include: {
relation: 'userConfig',
scope: {
fields: ['darkMode']
}
}
}); });
let roles = await models.RoleMapping.find({ let roles = await models.RoleMapping.find({

View File

@ -9,10 +9,11 @@ module.exports = Self => {
* @return {boolean} True for user with read privileges * @return {boolean} True for user with read privileges
*/ */
Self.hasReadRole = async(ctx, name, options) => { Self.hasReadRole = async(ctx, name, options) => {
const collection = await Self.findOne({where: {name}}, { const collection = await Self.findOne({
include: { include: {
relation: 'readRole' relation: 'readRole'
} },
where: {name}
}, options); }, options);
return await hasRole(ctx, collection, options); return await hasRole(ctx, collection, options);

View File

@ -34,6 +34,8 @@ async function test() {
app.boot(bootOptions, app.boot(bootOptions,
err => err ? reject(err) : resolve()); err => err ? reject(err) : resolve());
}); });
// FIXME: Workaround to wait for loopback to be ready
await app.models.Application.status();
const Jasmine = require('jasmine'); const Jasmine = require('jasmine');
const jasmine = new Jasmine(); const jasmine = new Jasmine();

View File

@ -1,9 +1,10 @@
FROM mariadb:10.7.3 FROM mariadb:10.7.5
ENV MYSQL_ROOT_PASSWORD root ENV MYSQL_ROOT_PASSWORD root
ENV TZ Europe/Madrid ENV TZ Europe/Madrid
ARG MOCKDATE=2001-01-01 11:00:00
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \ && apt-get install -y --no-install-recommends curl ca-certificates \
&& curl -sL https://apt.verdnatura.es/conf/verdnatura.gpg | apt-key add - \ && curl -sL https://apt.verdnatura.es/conf/verdnatura.gpg | apt-key add - \
@ -31,14 +32,15 @@ COPY \
import-changes.sh \ import-changes.sh \
config.ini \ config.ini \
dump/mysqlPlugins.sql \ dump/mysqlPlugins.sql \
dump/mockDate.sql \
dump/structure.sql \ dump/structure.sql \
dump/mockDate.sql \
dump/dumpedFixtures.sql \ dump/dumpedFixtures.sql \
./ ./
RUN gosu mysql docker-init.sh \ RUN gosu mysql docker-init.sh \
&& docker-dump.sh mysqlPlugins \ && docker-dump.sh mysqlPlugins \
&& docker-dump.sh mockDate \
&& docker-dump.sh structure \ && docker-dump.sh structure \
&& sed -i -e 's/@mockDate/'"$MOCKDATE"'/g' mockDate.sql \
&& docker-dump.sh mockDate \
&& docker-dump.sh dumpedFixtures \ && docker-dump.sh dumpedFixtures \
&& gosu mysql docker-temp-stop.sh && gosu mysql docker-temp-stop.sh

View File

@ -56,8 +56,6 @@ CREATE TABLE `vn`.`collectionWagonTicket` (
ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned NOT NULL; ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned NOT NULL;
ALTER TABLE `vn`.`wagon` ADD `label` int(11) unsigned NOT NULL; ALTER TABLE `vn`.`wagon` ADD `label` int(11) unsigned NOT NULL;
ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE;
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES VALUES
('WagonType', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), ('WagonType', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
@ -70,3 +68,4 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `pri
('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'), ('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'), ('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'); ('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi');

View File

@ -1,5 +0,0 @@
UPDATE vn.supplier s
JOIN vn.country c ON c.id = s.countryFk
SET s.nif = MID(REPLACE(s.nif, ' ', ''), 3, LENGTH(REPLACE(s.nif, ' ', '')) - 1)
WHERE s.isVies = TRUE
AND c.code = LEFT(REPLACE(s.nif, ' ', ''), 2);

View File

@ -1,5 +0,0 @@
UPDATE IGNORE vn.client c
JOIN vn.country co ON co.id = c.countryFk
SET c.fi = MID(REPLACE(c.fi, ' ', ''), 3, LENGTH(REPLACE(c.fi, ' ', '')) - 1)
WHERE c.isVies = TRUE
AND co.code = LEFT(REPLACE(c.fi, ' ', ''), 2);

View File

@ -27,7 +27,6 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalTyp
('Client', 'summary', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'summary', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateAddress', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'updateAddress', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateFiscalData', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'updateFiscalData', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateUser', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'uploadFile', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'uploadFile', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'campaignMetricsPdf', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'campaignMetricsPdf', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'campaignMetricsEmail', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'campaignMetricsEmail', '*', 'ALLOW', 'ROLE', 'employee'),

View File

@ -0,0 +1,77 @@
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `vn`.`zoneEstimatedDelivery` AS
select
`t`.`zoneFk` AS `zoneFk`,
cast(`util`.`VN_CURDATE`() + interval hour(ifnull(`zc`.`hour`, `z`.`hour`)) * 60 + minute(ifnull(`zc`.`hour`, `z`.`hour`)) minute as time) AS `hourTheoretical`,
cast(sum(`sv`.`volume`) as decimal(5, 1)) AS `totalVolume`,
cast(sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) as decimal(5, 1)) AS `remainingVolume`,
greatest(
ifnull(`lhp`.`m3`, 0),
ifnull(`dl`.`minSpeed`, 0)
) AS `speed`,
cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `hourEffective`,
floor(-sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0))) AS `minutesLess`,
cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `etc`
from
(
(
(
(
(
(
(
(
(
`vn`.`ticket` `t`
join `vn`.`ticketStateToday` `tst` on
(
`tst`.`ticket` = `t`.`id`
)
)
join `vn`.`state` `s` on
(
`s`.`id` = `tst`.`state`
)
)
join `vn`.`saleVolume` `sv` on
(
`sv`.`ticketFk` = `t`.`id`
)
)
left join `vn`.`lastHourProduction` `lhp` on
(
`lhp`.`warehouseFk` = `t`.`warehouseFk`
)
)
join `vn`.`warehouse` `w` on
(
`w`.`id` = `t`.`warehouseFk`
)
)
join `vn`.`warehouseAlias` `wa` on
(
`wa`.`id` = `w`.`aliasFk`
)
)
straight_join `vn`.`zone` `z` on
(
`z`.`id` = `t`.`zoneFk`
)
)
left join `vn`.`zoneClosure` `zc` on
(
`zc`.`zoneFk` = `t`.`zoneFk`
and `zc`.`dated` = `util`.`VN_CURDATE`()
)
)
left join `cache`.`departure_limit` `dl` on
(
`dl`.`warehouse_id` = `t`.`warehouseFk`
and `dl`.`fecha` = `util`.`VN_CURDATE`()
)
)
where
`w`.`hasProduction` <> 0
and cast(`t`.`shipped` as date) = `util`.`VN_CURDATE`()
group by
`t`.`zoneFk`;

View File

@ -1 +1 @@
ALTER TABLE `vn`.`ticketConfig` ADD daysForWarningClaim INT DEFAULT 2 NOT NULL COMMENT 'dias restantes hasta que salte el aviso de reclamación fuerade plazo'; ALTER TABLE `vn`.`ticketConfig` ADD daysForWarningClaim INT DEFAULT 2 NOT NULL COMMENT 'dias restantes hasta que salte el aviso de reclamación fuera de plazo';

View File

@ -0,0 +1,5 @@
UPDATE `vn`.`supplier` s
JOIN `vn`.`country` c ON c.id = s.countryFk
SET s.nif = MID(REPLACE(s.nif, ' ', ''), 3, LENGTH(REPLACE(s.nif, ' ', '')) - 1)
WHERE s.isVies = TRUE
AND c.code = LEFT(REPLACE(s.nif, ' ', ''), 2);

View File

@ -0,0 +1,5 @@
UPDATE IGNORE `vn`.`client` c
JOIN `vn`.`country` co ON co.id = c.countryFk
SET c.fi = MID(REPLACE(c.fi, ' ', ''), 3, LENGTH(REPLACE(c.fi, ' ', '')) - 1)
WHERE c.isVies = TRUE
AND co.code = LEFT(REPLACE(c.fi, ' ', ''), 2);

View File

@ -0,0 +1,12 @@
-- vn.companyL10n source
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `vn`.`companyL10n` AS
select
`c`.`id` AS `id`,
ifnull(`ci`.`footnotes`, `c`.`footnotes`) AS `footnotes`
from
(`vn`.`company` `c`
left join `vn`.`companyI18n` `ci` on
(`ci`.`companyFk` = `c`.`id`
and `ci`.`lang` = `util`.`LANG`()));

View File

@ -0,0 +1,73 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`clientCreate`(
vFirstname VARCHAR(50),
vSurnames VARCHAR(50),
vFi VARCHAR(9),
vAddress TEXT,
vPostcode CHAR(5),
vCity VARCHAR(25),
vProvinceFk SMALLINT(5),
vCompanyFk SMALLINT(5),
vPhone VARCHAR(11),
vEmail VARCHAR(255),
vUserFk INT)
BEGIN
/**
* Create new client
*
*/
DECLARE vPayMethodFk INT DEFAULT 4;
DECLARE vDueDay INT DEFAULT 5;
DECLARE vDefaultCredit DECIMAL(10, 2) DEFAULT 300.00;
DECLARE vIsTaxDataChecked TINYINT(1) DEFAULT 1;
DECLARE vHasCoreVnl BOOLEAN DEFAULT TRUE;
DECLARE vMandateTypeFk INT DEFAULT 2;
INSERT INTO `client` (
id,
name,
street,
fi,
phone,
email,
provinceFk,
city,
postcode,
socialName,
payMethodFk,
dueDay,
credit,
isTaxDataChecked,
hasCoreVnl,
isEqualizated)
VALUES (
vUserFk,
CONCAT(vFirstname, ' ', vSurnames),
vAddress,
TRIM(vFi),
vPhone,
vEmail,
vProvinceFk,
vCity,
vPostcode,
CONCAT(vSurnames, ' ', vFirstname),
vPayMethodFk,
vDueDay,
vDefaultCredit,
vIsTaxDataChecked,
vHasCoreVnl,
FALSE
) ON duplicate key update
payMethodFk = vPayMethodFk,
dueDay = vDueDay,
credit = vDefaultCredit,
isTaxDataChecked = vIsTaxDataChecked,
hasCoreVnl = vHasCoreVnl,
isActive = TRUE;
IF (SELECT COUNT(*) FROM mandate WHERE clientFk = vUserFk AND companyFk = vCompanyFk AND mandateTypeFk = vMandateTypeFk) = 0 THEN
INSERT INTO mandate (clientFk, companyFk, mandateTypeFk)
VALUES (vUserFk, vCompanyFk, vMandateTypeFk);
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,14 @@
INSERT INTO `vn`.`businessType` (`code`, `description`)
VALUES ('worker','Trabajador');
ALTER TABLE `vn`.`workerConfig` ADD businessTypeFk varchar(100) NULL
COMMENT 'Tipo de negocio por defecto al dar de alta un trabajador nuevo';
UPDATE `vn`.`workerConfig`
SET businessTypeFk = 'worker'
WHERE id = 1;
UPDATE `vn`.`client` c
JOIN `vn`.`worker` w ON w.id = c.id
SET c.name = REPLACE(c.name, 'TR ', ''),
c.businessTypeFk = 'worker';

View File

@ -0,0 +1,254 @@
DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_new`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`(
vSerial VARCHAR(255),
vInvoiceDate DATE,
vTaxArea VARCHAR(25),
OUT vNewInvoiceId INT)
BEGIN
/**
* Creación de facturas emitidas.
* requiere previamente tabla tmp.ticketToInvoice(id).
*
* @param vSerial serie a la cual se hace la factura
* @param vInvoiceDate fecha de la factura
* @param vTaxArea tipo de iva en relacion a la empresa y al cliente
* @param vNewInvoiceId id de la factura que se acaba de generar
* @return vNewInvoiceId
*/
DECLARE vIsAnySaleToInvoice BOOL;
DECLARE vIsAnyServiceToInvoice BOOL;
DECLARE vNewRef VARCHAR(255);
DECLARE vWorker INT DEFAULT account.myUser_getId();
DECLARE vCompanyFk INT;
DECLARE vInterCompanyFk INT;
DECLARE vClientFk INT;
DECLARE vCplusStandardInvoiceTypeFk INT DEFAULT 1;
DECLARE vCplusCorrectingInvoiceTypeFk INT DEFAULT 6;
DECLARE vCplusSimplifiedInvoiceTypeFk INT DEFAULT 2;
DECLARE vCorrectingSerial VARCHAR(1) DEFAULT 'R';
DECLARE vSimplifiedSerial VARCHAR(1) DEFAULT 'S';
DECLARE vNewInvoiceInFk INT;
DECLARE vIsInterCompany BOOL DEFAULT FALSE;
DECLARE vIsCEESerial BOOL DEFAULT FALSE;
DECLARE vIsCorrectInvoiceDate BOOL;
DECLARE vMaxShipped DATE;
SET vInvoiceDate = IFNULL(vInvoiceDate, util.VN_CURDATE());
SELECT t.clientFk,
t.companyFk,
MAX(DATE(t.shipped)),
DATE(vInvoiceDate) >= invoiceOut_getMaxIssued(
vSerial,
t.companyFk,
YEAR(vInvoiceDate))
INTO vClientFk,
vCompanyFk,
vMaxShipped,
vIsCorrectInvoiceDate
FROM tmp.ticketToInvoice tt
JOIN ticket t ON t.id = tt.id;
IF(vMaxShipped > vInvoiceDate) THEN
CALL util.throw("Invoice date can't be less than max date");
END IF;
IF NOT vIsCorrectInvoiceDate THEN
CALL util.throw('Exists an invoice with a previous date');
END IF;
-- Eliminem de tmp.ticketToInvoice els tickets que no han de ser facturats
DELETE ti.*
FROM tmp.ticketToInvoice ti
JOIN ticket t ON t.id = ti.id
JOIN sale s ON s.ticketFk = t.id
JOIN item i ON i.id = s.itemFk
JOIN supplier su ON su.id = t.companyFk
JOIN client c ON c.id = t.clientFk
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id AND itc.countryFk = su.countryFk
WHERE (YEAR(t.shipped) < 2001 AND t.isDeleted)
OR c.isTaxDataChecked = FALSE
OR t.isDeleted
OR c.hasToInvoice = FALSE
OR itc.id IS NULL;
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100) <> 0
INTO vIsAnySaleToInvoice
FROM tmp.ticketToInvoice t
JOIN sale s ON s.ticketFk = t.id;
SELECT COUNT(*) > 0 INTO vIsAnyServiceToInvoice
FROM tmp.ticketToInvoice t
JOIN ticketService ts ON ts.ticketFk = t.id;
IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice)
AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase())
THEN
-- el trigger añade el siguiente Id_Factura correspondiente a la vSerial
INSERT INTO invoiceOut(
ref,
serial,
issued,
clientFk,
dued,
companyFk,
cplusInvoiceType477Fk
)
SELECT
1,
vSerial,
vInvoiceDate,
vClientFk,
getDueDate(vInvoiceDate, dueDay),
vCompanyFk,
IF(vSerial = vCorrectingSerial,
vCplusCorrectingInvoiceTypeFk,
IF(vSerial = vSimplifiedSerial,
vCplusSimplifiedInvoiceTypeFk,
vCplusStandardInvoiceTypeFk))
FROM client
WHERE id = vClientFk;
SET vNewInvoiceId = LAST_INSERT_ID();
SELECT `ref`
INTO vNewRef
FROM invoiceOut
WHERE id = vNewInvoiceId;
UPDATE ticket t
JOIN tmp.ticketToInvoice ti ON ti.id = t.id
SET t.refFk = vNewRef;
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
FROM tmp.ticketToInvoice ti
LEFT JOIN ticketState ts ON ti.id = ts.ticket
JOIN state s
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
INSERT INTO ticketTracking(stateFk,ticketFk,workerFk)
SELECT * FROM tmp.updateInter;
CALL invoiceExpenceMake(vNewInvoiceId);
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
UPDATE invoiceOut io
JOIN (
SELECT SUM(amount) total
FROM invoiceOutExpence
WHERE invoiceOutFk = vNewInvoiceId
) base
JOIN (
SELECT SUM(vat) total
FROM invoiceOutTax
WHERE invoiceOutFk = vNewInvoiceId
) vat
SET io.amount = base.total + vat.total
WHERE io.id = vNewInvoiceId;
DROP TEMPORARY TABLE tmp.updateInter;
SELECT COUNT(*), id
INTO vIsInterCompany, vInterCompanyFk
FROM company
WHERE clientFk = vClientFk;
IF (vIsInterCompany) THEN
INSERT INTO invoiceIn(supplierFk, supplierRef, issued, companyFk)
SELECT vCompanyFk, vNewRef, vInvoiceDate, vInterCompanyFk;
SET vNewInvoiceInFk = LAST_INSERT_ID();
DROP TEMPORARY TABLE IF EXISTS tmp.ticket;
CREATE TEMPORARY TABLE tmp.ticket
(KEY (ticketFk))
ENGINE = MEMORY
SELECT id ticketFk
FROM tmp.ticketToInvoice;
CALL `ticket_getTax`('NATIONAL');
SET @vTaxableBaseServices := 0.00;
SET @vTaxCodeGeneral := NULL;
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInFk,
@vTaxableBaseServices,
sub.expenceFk,
sub.taxTypeSageFk,
sub.transactionTypeSageFk
FROM (
SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase,
i.expenceFk,
i.taxTypeSageFk,
i.transactionTypeSageFk,
@vTaxCodeGeneral := i.taxClassCodeFk
FROM tmp.ticketServiceTax tst
JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code
WHERE i.isService
HAVING taxableBase
) sub;
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
SELECT vNewInvoiceInFk,
SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral,
@vTaxableBaseServices, 0) taxableBase,
i.expenceFk,
i.taxTypeSageFk ,
i.transactionTypeSageFk
FROM tmp.ticketTax tt
JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code
WHERE !i.isService
GROUP BY tt.pgcFk
HAVING taxableBase
ORDER BY tt.priority;
CALL invoiceInDueDay_calculate(vNewInvoiceInFk);
SELECT COUNT(*) INTO vIsCEESerial
FROM invoiceOutSerial
WHERE code = vSerial;
IF vIsCEESerial THEN
INSERT INTO invoiceInIntrastat (
invoiceInFk,
intrastatFk,
amount,
stems,
countryFk,
net)
SELECT
vNewInvoiceInFk,
i.intrastatFk,
SUM(CAST((s.quantity * s.price * (100 - s.discount) / 100 ) AS DECIMAL(10, 2))),
SUM(CAST(IFNULL(i.stems, 1) * s.quantity AS DECIMAL(10, 2))),
su.countryFk,
CAST(SUM(IFNULL(i.stems, 1)
* s.quantity
* IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000) AS DECIMAL(10, 2))
FROM sale s
JOIN ticket t ON s.ticketFk = t.id
JOIN supplier su ON su.id = t.companyFk
JOIN item i ON i.id = s.itemFk
LEFT JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk
WHERE t.refFk = vNewRef
GROUP BY i.intrastatFk;
END IF;
DROP TEMPORARY TABLE tmp.ticket;
DROP TEMPORARY TABLE tmp.ticketAmount;
DROP TEMPORARY TABLE tmp.ticketTax;
DROP TEMPORARY TABLE tmp.ticketServiceTax;
END IF;
END IF;
DROP TEMPORARY TABLE `tmp`.`ticketToInvoice`;
END$$
DELIMITER ;

View File

@ -0,0 +1 @@
ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE;

View File

@ -0,0 +1,20 @@
-- vn.defaulter source
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `vn`.`defaulter` AS
select
`d`.`clientFk` AS `clientFk`,
`d`.`created` AS `created`,
`d`.`amount` AS `amount`,
`d`.`defaulterSinced` AS `defaulterSinced`,
`d`.`hasChanged` AS `hasChanged`,
`c`.`countryFk` AS `country`,
`c`.`payMethodFk` AS `payMethod`
from
(((`bs`.`defaulter` `d`
join `vn`.`client` `c` on
(`c`.`id` = `d`.`clientFk`))
join `vn`.`country` `co` on
(`co`.`id` = `c`.`countryFk`))
join `vn`.`payMethod` `pm` on
(`pm`.`id` = `c`.`payMethodFk`));

View File

@ -0,0 +1,127 @@
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;
DROP TEMPORARY TABLE IF EXISTS tmp.stock;
CREATE 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 < vDateFuture
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;
DROP TEMPORARY TABLE IF EXISTS tmp.filter;
CREATE 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,
origin.futureAgency,
dest.lines,
dest.liters,
origin.futureLines - origin.hasStock AS notMovableLines,
(origin.futureLines = origin.hasStock) AS isFullMovable,
origin.classColor,
dest.classColor futureClassColor
FROM (
SELECT
s.ticketFk,
t.workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
t.addressFk,
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,
st.classColor
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
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
JOIN (
SELECT
t.id ticketFk,
t.addressFk,
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
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 != 0;
DROP TEMPORARY TABLE tmp.stock;
END$$
DELIMITER ;

View File

@ -0,0 +1,72 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canbePostponed`(vOriginDated DATE, vFutureDated DATE, vWarehouseFk INT)
BEGIN
/**
* Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro
*
* @param vOriginDated Fecha en cuestión
* @param vFutureDated Fecha en el futuro a sondear
* @param vWarehouseFk Identificador de vn.warehouse
*/
DROP TEMPORARY TABLE IF EXISTS tmp.filter;
CREATE TEMPORARY TABLE tmp.filter
(INDEX (id))
SELECT sv.ticketFk id,
sub2.id futureId,
GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt,
CAST(sum(litros) AS DECIMAL(10,0)) liters,
CAST(count(*) AS DECIMAL(10,0)) `lines`,
st.name state,
sub2.iptd futureIpt,
sub2.state futureState,
t.clientFk,
t.warehouseFk,
ts.alertLevel,
t.shipped,
sub2.shipped futureShipped,
t.workerFk,
st.code stateCode,
sub2.code futureStateCode,
st.classColor
FROM vn.saleVolume sv
JOIN vn.sale s ON s.id = sv.saleFk
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.ticket t ON t.id = sv.ticketFk
JOIN vn.address a ON a.id = t.addressFk
JOIN vn.province p ON p.id = a.provinceFk
JOIN vn.country c ON c.id = p.countryFk
JOIN vn.ticketState ts ON ts.ticketFk = t.id
JOIN vn.state st ON st.id = ts.stateFk
JOIN vn.alertLevel al ON al.id = ts.alertLevel
LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id
LEFT JOIN (
SELECT *
FROM (
SELECT
t.addressFk,
t.id,
t.shipped,
st.name state,
st.code code,
GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) iptd
FROM vn.ticket t
JOIN vn.ticketState ts ON ts.ticketFk = t.id
JOIN vn.state st ON st.id = ts.stateFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
WHERE t.shipped BETWEEN vFutureDated
AND util.dayend(vFutureDated)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
) sub
GROUP BY sub.addressFk
) sub2 ON sub2.addressFk = t.addressFk AND t.id != sub2.id
WHERE t.shipped BETWEEN vOriginDated AND util.dayend(vOriginDated)
AND t.warehouseFk = vWarehouseFk
AND al.code = 'FREE'
AND tp.ticketFk IS NULL
GROUP BY sv.ticketFk
HAVING futureId;
END$$
DELIMITER ;

View File

@ -0,0 +1,7 @@
ALTER TABLE `vn`.`workerConfig` ADD payMethodFk tinyint(3) unsigned NULL;
ALTER TABLE `vn`.`workerConfig` ADD CONSTRAINT workerConfig_FK FOREIGN KEY (roleFk) REFERENCES account.`role`(id) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `vn`.`workerConfig` ADD CONSTRAINT workerConfig_FK_1 FOREIGN KEY (payMethodFk) REFERENCES `vn`.`payMethod`(id) ON DELETE SET NULL ON UPDATE CASCADE;
UPDATE `vn`.`workerConfig`
SET payMethodFk = 4
WHERE id=1;

View File

@ -0,0 +1,127 @@
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;
DROP TEMPORARY TABLE IF EXISTS tmp.stock;
CREATE 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 < vDateFuture
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;
DROP TEMPORARY TABLE IF EXISTS tmp.filter;
CREATE 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,
origin.futureAgency,
dest.lines,
dest.liters,
origin.futureLines - origin.hasStock AS notMovableLines,
(origin.futureLines = origin.hasStock) AS isFullMovable,
origin.classColor futureClassColor,
dest.classColor
FROM (
SELECT
s.ticketFk,
t.workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
t.addressFk,
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,
st.classColor
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
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
JOIN (
SELECT
t.id ticketFk,
t.addressFk,
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
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 != 0;
DROP TEMPORARY TABLE tmp.stock;
END$$
DELIMITER ;

View File

@ -0,0 +1,74 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canbePostponed`(vOriginDated DATE, vFutureDated DATE, vWarehouseFk INT)
BEGIN
/**
* Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro
*
* @param vOriginDated Fecha en cuestión
* @param vFutureDated Fecha en el futuro a sondear
* @param vWarehouseFk Identificador de vn.warehouse
*/
DROP TEMPORARY TABLE IF EXISTS tmp.filter;
CREATE TEMPORARY TABLE tmp.filter
(INDEX (id))
SELECT sv.ticketFk id,
sub2.id futureId,
GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt,
CAST(sum(litros) AS DECIMAL(10,0)) liters,
CAST(count(*) AS DECIMAL(10,0)) `lines`,
st.name state,
sub2.iptd futureIpt,
sub2.state futureState,
t.clientFk,
t.warehouseFk,
ts.alertLevel,
t.shipped,
sub2.shipped futureShipped,
t.workerFk,
st.code stateCode,
sub2.code futureStateCode,
st.classColor,
sub2.classColor futureClassColor
FROM vn.saleVolume sv
JOIN vn.sale s ON s.id = sv.saleFk
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.ticket t ON t.id = sv.ticketFk
JOIN vn.address a ON a.id = t.addressFk
JOIN vn.province p ON p.id = a.provinceFk
JOIN vn.country c ON c.id = p.countryFk
JOIN vn.ticketState ts ON ts.ticketFk = t.id
JOIN vn.state st ON st.id = ts.stateFk
JOIN vn.alertLevel al ON al.id = ts.alertLevel
LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id
LEFT JOIN (
SELECT *
FROM (
SELECT
t.addressFk,
t.id,
t.shipped,
st.name state,
st.code,
st.classColor,
GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) iptd
FROM vn.ticket t
JOIN vn.ticketState ts ON ts.ticketFk = t.id
JOIN vn.state st ON st.id = ts.stateFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
WHERE t.shipped BETWEEN vFutureDated
AND util.dayend(vFutureDated)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
) sub
GROUP BY sub.addressFk
) sub2 ON sub2.addressFk = t.addressFk AND t.id != sub2.id
WHERE t.shipped BETWEEN vOriginDated AND util.dayend(vOriginDated)
AND t.warehouseFk = vWarehouseFk
AND al.code = 'FREE'
AND tp.ticketFk IS NULL
GROUP BY sv.ticketFk
HAVING futureId;
END$$
DELIMITER ;

View File

View File

@ -0,0 +1,28 @@
CREATE TABLE `vn`.`buyConfig` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`monthsAgo` int(11) NOT NULL DEFAULT 6 COMMENT 'Meses desde la última compra',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
CREATE TABLE `vn`.`travelConfig` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`warehouseInFk` smallint(6) unsigned NOT NULL DEFAULT 8 COMMENT 'Warehouse de origen',
`warehouseOutFk` smallint(6) unsigned NOT NULL DEFAULT 60 COMMENT 'Warehouse destino',
`agencyFk` int(11) NOT NULL DEFAULT 1378 COMMENT 'Agencia por defecto',
`companyFk` smallint(5) unsigned NOT NULL DEFAULT 442 COMMENT 'Compañía por defecto',
PRIMARY KEY (`id`),
KEY `travelConfig_FK` (`warehouseInFk`),
KEY `travelConfig_FK_1` (`warehouseOutFk`),
KEY `travelConfig_FK_2` (`agencyFk`),
KEY `travelConfig_FK_3` (`companyFk`),
CONSTRAINT `travelConfig_FK` FOREIGN KEY (`warehouseInFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `travelConfig_FK_1` FOREIGN KEY (`warehouseOutFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `travelConfig_FK_2` FOREIGN KEY (`agencyFk`) REFERENCES `agencyMode` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `travelConfig_FK_3` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Entry', 'addFromPackaging', 'WRITE', 'ALLOW', 'ROLE', 'production'),
('Entry', 'addFromBuy', 'WRITE', 'ALLOW', 'ROLE', 'production'),
('Supplier', 'getItemsPackaging', 'READ', 'ALLOW', 'ROLE', 'production');

View File

@ -0,0 +1,3 @@
ALTER TABLE `vn`.`sector` DROP COLUMN `printerFk`;
ALTER TABLE `vn`.`sector` ADD COLUMN `mainPrinterFk` tinyint(3) unsigned;
ALTER TABLE `vn`.`sector` ADD CONSTRAINT sector_FK_1 FOREIGN KEY (mainPrinterFk) REFERENCES vn.printer(id) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1 @@
ALTER TABLE `vn`.`ticket` MODIFY COLUMN warehouseFk smallint(6) unsigned DEFAULT NULL NULL;

View File

@ -0,0 +1,121 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Ticket', 'editDiscount', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Ticket', 'editDiscount', 'WRITE', 'ALLOW', 'ROLE', 'salesPerson'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'salesAssistant'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'deliveryBoss'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'buyer'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'claimManager'),
('Ticket', 'deleteTicketWithPartPrepared', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Ticket', 'editZone', 'WRITE', 'ALLOW', 'ROLE', 'deliveryBoss'),
('State', 'editableStates', 'READ', 'ALLOW', 'ROLE', 'employee'),
('State', 'seeEditableStates', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('State', 'seeEditableStates', 'READ', 'ALLOW', 'ROLE', 'production'),
('State', 'isSomeEditable', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('State', 'isAllEditable', 'READ', 'ALLOW', 'ROLE', 'production'),
('State', 'isAllEditable', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Agency', 'seeExpired', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Agency', 'seeExpired', 'READ', 'ALLOW', 'ROLE', 'productionBoss'),
('Claim', 'createAfterDeadline', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Client', 'editAddressLogifloraAllowed', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Client', 'editFiscalDataWithoutTaxDataCheck', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Client', 'editVerifiedDataWithoutTaxDataCheck', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Client', 'editCredit', 'WRITE', 'ALLOW', 'ROLE', 'financialBoss'),
('Client', 'isNotEditableCredit', 'WRITE', 'ALLOW', 'ROLE', 'financialBoss'),
('InvoiceOut', 'canCreatePdf', 'WRITE', 'ALLOW', 'ROLE', 'invoicing'),
('Supplier', 'editPayMethodCheck', 'WRITE', 'ALLOW', 'ROLE', 'financial'),
('Worker', 'isTeamBoss', 'WRITE', 'ALLOW', 'ROLE', 'teamBoss'),
('Worker', 'forceIsSubordinate', 'READ', 'ALLOW', 'ROLE', 'hr'),
('Claim', 'editState', 'WRITE', 'ALLOW', 'ROLE', 'claimManager');
DELETE FROM `salix`.`ACL`
WHERE
model = 'Claim'
AND property = '*'
AND accessType = '*';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Claim', 'find', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'findById', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'findOne', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'getSummary', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'updateClaim', 'WRITE', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'regularizeClaim', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'updateClaimDestination', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'downloadFile', 'READ', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'filter', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'logs', 'READ', 'ALLOW', 'ROLE', 'claimManager');
DELETE FROM `salix`.`ACL`
WHERE
model = 'Ticket'
AND property = '*'
AND accessType = '*';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Ticket', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getVolume', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getTotalVolume', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'summary', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'priceDifference', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'componentUpdate', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'new', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'isEditable', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'setDeleted', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'restore', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getSales', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getSalesPersonMana', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'filter', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'makeInvoice', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'updateEditableTicket', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'updateDiscount', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'transferSales', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'sendSms', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'isLocked', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'freightCost', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getComponentsSum', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'delivery'), -- Change Priority in Route tickets
('Ticket', 'deliveryNoteCsv', 'READ', 'ALLOW', 'ROLE', 'employee');
DELETE FROM `salix`.`ACL`
WHERE
model = 'State'
AND property = '*'
AND accessType = 'READ';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('State', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'),
('State', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'),
('State', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee');
DELETE FROM `salix`.`ACL`
WHERE
model = 'Worker'
AND property = '*'
AND accessType = 'READ';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Worker', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'filter', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'getWorkedHours', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'active', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'activeWithRole', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'uploadFile', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
('Worker', 'contracts', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'holidays', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'activeContract', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'activeWithInheritedRole', 'READ', 'ALLOW', 'ROLE', 'employee');
DELETE FROM `salix`.`ACL`
WHERE model = 'Client'
AND property = 'updateUser'
AND accessType = '*';

View File

File diff suppressed because one or more lines are too long

View File

@ -179,6 +179,8 @@ INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAd
(2, 'printer2', 'path2', 1, 1 , NULL), (2, 'printer2', 'path2', 1, 1 , NULL),
(4, 'printer4', 'path4', 0, NULL, '10.1.10.4'); (4, 'printer4', 'path4', 0, NULL, '10.1.10.4');
UPDATE `vn`.`sector` SET mainPrinterFk = 1 WHERE id = 1;
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`) INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`)
VALUES VALUES
(1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106, NULL, NULL), (1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106, NULL, NULL),
@ -349,20 +351,20 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`)
(4, 'GCN Channel'), (4, 'GCN Channel'),
(5, 'The Newspaper'); (5, 'The Newspaper');
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`,`mailAddress`,`hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`, `businessTypeFk`) 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`)
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, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (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'),
(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, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (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'),
(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, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (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'),
(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, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (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'),
(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, 1, NULL, 0, 0, 18, 0, 1, 'florist'), (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'),
(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, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist'), (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'),
(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, 1, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist'), (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'),
(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, 1, NULL, 0, 0, 19, 0, 1, 'florist'), (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'),
(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, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist'), (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'),
(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, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist'), (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'),
(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, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others'), (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'),
(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, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others'); (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');
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
@ -707,7 +709,7 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
(15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE()), (15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE()), (16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE()), (17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, util.VN_CURDATE()), (18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +12 HOUR)),
(19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE()), (19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE()),
(20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)), (20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)),
(21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)), (21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)),
@ -905,7 +907,7 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
`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, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V', 0, 15,3), (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'EMB', 0, NULL, 'V', 0, 15,3),
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0, 10,2), (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0, 10,2),
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, 5,5), (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, 5,5),
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL,NULL), (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL,NULL),
@ -1940,6 +1942,16 @@ INSERT INTO `pbx`.`sip`(`user_id`, `extension`)
(5, 1102), (5, 1102),
(9, 1201); (9, 1201);
INSERT INTO `vn`.`professionalCategory` (`id`, `name`, `level`, `dayBreak`)
VALUES
(1, 'employee', NULL, NULL),
(2, 'florist', NULL, NULL);
INSERT INTO `vn`.`calendarType` (`id`, `description`, `hoursWeek`, `isPartial`)
VALUES
(1, 'General schedule', 40, 0);
DROP TEMPORARY TABLE IF EXISTS tmp.worker; DROP TEMPORARY TABLE IF EXISTS tmp.worker;
CREATE TEMPORARY TABLE tmp.worker CREATE TEMPORARY TABLE tmp.worker
(PRIMARY KEY (id)) (PRIMARY KEY (id))
@ -1968,7 +1980,7 @@ UPDATE `vn`.`business`
WHERE `id`= 1106; WHERE `id`= 1106;
UPDATE `vn`.`business` b UPDATE `vn`.`business` b
SET b.`workerBusinessProfessionalCategoryFk` = 31 SET b.`workerBusinessProfessionalCategoryFk` = 2
WHERE b.`workerFk` = 1110; WHERE b.`workerFk` = 1110;
UPDATE `vn`.`business` b UPDATE `vn`.`business` b
@ -2719,6 +2731,7 @@ INSERT INTO `util`.`notification` (`id`, `name`, `description`)
VALUES VALUES
(1, 'print-email', 'notification fixture one'), (1, 'print-email', 'notification fixture one'),
(2, 'invoice-electronic', 'A electronic invoice has been generated'), (2, 'invoice-electronic', 'A electronic invoice has been generated'),
(3, 'not-main-printer-configured', 'A printer distinct than main has been configured'),
(4, 'supplier-pay-method-update', 'A supplier pay method has been updated'); (4, 'supplier-pay-method-update', 'A supplier pay method has been updated');
INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`) INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
@ -2773,8 +2786,22 @@ INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldIns
(7, 18, 'update', 'Sale', '{"quantity":1}', '{"quantity":10}', 1, NULL), (7, 18, 'update', 'Sale', '{"quantity":1}', '{"quantity":10}', 1, NULL),
(7, 18, 'update', 'Ticket', '{"quantity":1,"concept":"Chest ammo box"}', '{"quantity":10,"concept":"Chest ammo box"}', 1, NULL), (7, 18, 'update', 'Ticket', '{"quantity":1,"concept":"Chest ammo box"}', '{"quantity":10,"concept":"Chest ammo box"}', 1, NULL),
(7, 18, 'update', 'Sale', '{"price":3}', '{"price":5}', 1, NULL), (7, 18, 'update', 'Sale', '{"price":3}', '{"price":5}', 1, NULL),
(7, 18, 'update', NULL, NULL, NULL, NULL, "Cambio cantidad Melee weapon heavy shield 1x0.5m de '5' a '10'"); (7, 18, 'update', NULL, NULL, NULL, NULL, "Cambio cantidad Melee weapon heavy shield 1x0.5m de '5' a '10'"),
(16, 9, 'update', 'Sale', '{"quantity":10,"concept":"Shield", "price": 10.5, "itemFk": 1}', '{"quantity":8,"concept":"Shield", "price": 10.5, "itemFk": 1}' , 5689, 'Shield');
INSERT INTO `vn`.`ticketLog` (originFk, userFk, `action`, creationDate, changedModel, changedModelId, changedModelValue, oldInstance, newInstance, description)
VALUES
(1, NULL, 'delete', '2001-06-09 11:00:04', 'Ticket', 45, 'Spider Man' , NULL, NULL, NULL),
(1, 18, 'select', '2001-06-09 11:00:03', 'Ticket', 45, 'Spider Man' , NULL, NULL, NULL),
(1, NULL, 'update', '2001-05-09 10:00:02', 'Sale', 69854, 'Armor' , '{"isPicked": false}','{"isPicked": true}', NULL),
(1, 18, 'update', '2001-01-01 10:05:01', 'Sale', 69854, 'Armor' , NULL, NULL, 'Armor quantity changed from ''15'' to ''10'''),
(1, NULL, 'delete', '2001-01-01 10:00:10', 'Sale', 5689, 'Shield' , '{"quantity":10,"concept":"Shield"}', NULL, NULL),
(1, 18, 'insert', '2000-12-31 15:00:05', 'Sale', 69854, 'Armor' , NULL,'{"quantity":15,"concept":"Armor", "price": 345.99, "itemFk": 2}', NULL),
(1, 18, 'update', '2000-12-28 08:40:45', 'Ticket', 45, 'Spider Man' , '{"warehouseFk":60,"shipped":"2023-05-16T22:00:00.000Z","nickname":"Super Man","isSigned":true,"isLabeled":true,"isPrinted":true,"packages":0,"hour":0,"isBlocked":false,"hasPriority":false,"companyFk":442,"landed":"2023-05-17T22:00:00.000Z","isBoxed":true,"isDeleted":true,"zoneFk":713,"zonePrice":13,"zoneBonus":0}','{"warehouseFk":61,"shipped":"2023-05-17T22:00:00.000Z","nickname":"Spider Man","isSigned":false,"isLabeled":false,"isPrinted":false,"packages":1,"hour":0,"isBlocked":true,"hasPriority":true,"companyFk":443,"landed":"2023-05-18T22:00:00.000Z","isBoxed":false,"isDeleted":false,"zoneFk":713,"zonePrice":13,"zoneBonus":1}', NULL),
(1, 18, 'select', '2000-12-27 03:40:30', 'Ticket', 45, NULL , NULL, NULL, NULL),
(1, 18, 'insert', '2000-04-10 09:40:15', 'Sale', 5689, 'Shield' , NULL, '{"quantity":10,"concept":"Shield", "price": 10.5, "itemFk": 1}', NULL),
(1, 18, 'insert', '1999-05-09 10:00:00', 'Ticket', 45, 'Super Man' , NULL, '{"id":45,"clientFk":8608,"warehouseFk":60,"shipped":"2023-05-16T22:00:00.000Z","nickname":"Super Man","addressFk":48637,"isSigned":true,"isLabeled":true,"isPrinted":true,"packages":0,"hour":0,"created":"2023-05-16T11:42:56.000Z","isBlocked":false,"hasPriority":false,"companyFk":442,"agencyModeFk":639,"landed":"2023-05-17T22:00:00.000Z","isBoxed":true,"isDeleted":true,"zoneFk":713,"zonePrice":13,"zoneBonus":0}', NULL);
INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`) INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`)
VALUES VALUES
(0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all');
@ -2801,9 +2828,9 @@ INSERT INTO `vn`.`payDemDetail` (`id`, `detail`)
VALUES VALUES
(1, 1); (1, 1);
INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`, `payMethodFk`, `businessTypeFk`)
VALUES VALUES
(1, NULL, 1); (1, NULL, 1, 4, 'worker');
INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`) INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`)
VALUES VALUES
@ -2863,6 +2890,10 @@ 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 `vn`.`travelConfig` (`id`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `companyFk`)
VALUES
(1, 1, 1, 1, 442);
INSERT INTO `vn`.`buyConfig` (`id`, `monthsAgo`)
VALUES
(1, 6);

View File

@ -1,42 +1,33 @@
CREATE SCHEMA IF NOT EXISTS `util`; DROP FUNCTION IF EXISTS `util`.`mockTime`;
USE `util`;
DELIMITER ;; DELIMITER $$
DROP FUNCTION IF EXISTS `util`.`mockedDate`; $$
CREATE FUNCTION `util`.`mockedDate`() CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`mockTime`() RETURNS datetime
RETURNS DATETIME DETERMINISTIC
DETERMINISTIC
BEGIN BEGIN
RETURN CONVERT_TZ('2001-01-01 11:00:00', 'utc', 'Europe/Madrid'); RETURN CONVERT_TZ('@mockDate', 'utc', 'Europe/Madrid');
END ;; END$$
DELIMITER ; DELIMITER ;
DELIMITER ;; DROP FUNCTION IF EXISTS `util`.`mockUtcTime`;
DROP FUNCTION IF EXISTS `util`.`VN_CURDATE`;
CREATE FUNCTION `util`.`VN_CURDATE`() DELIMITER $$
RETURNS DATE $$
DETERMINISTIC CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`mockUtcTime`() RETURNS datetime
DETERMINISTIC
BEGIN BEGIN
RETURN DATE(mockedDate()); RETURN CONVERT_TZ('@mockDate', 'utc', 'Europe/Madrid');
END ;; END$$
DELIMITER ; DELIMITER ;
DELIMITER ;; DROP FUNCTION IF EXISTS `util`.`mockTimeBase`;
DROP FUNCTION IF EXISTS `util`.`VN_CURTIME`;
CREATE FUNCTION `util`.`VN_CURTIME`() DELIMITER $$
RETURNS TIME $$
DETERMINISTIC CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`mockTimeBase`(vIsUtc BOOL) RETURNS datetime
DETERMINISTIC
BEGIN BEGIN
RETURN TIME(mockedDate()); RETURN CONVERT_TZ('@mockDate', 'utc', 'Europe/Madrid');
END ;; END$$
DELIMITER ; DELIMITER ;
DELIMITER ;;
DROP FUNCTION IF EXISTS `util`.`VN_NOW`;
CREATE FUNCTION `util`.`VN_NOW`()
RETURNS DATETIME
DETERMINISTIC
BEGIN
RETURN mockedDate();
END ;;
DELIMITER ;

File diff suppressed because it is too large Load Diff

View File

@ -100,11 +100,8 @@ dump_tables ${TABLES[@]}
TABLES=( TABLES=(
postgresql postgresql
calendar_labour_type
labour_agreement labour_agreement
media_type media_type
professional_category
profile_type
) )
dump_tables ${TABLES[@]} dump_tables ${TABLES[@]}

View File

@ -93,12 +93,5 @@ mysqldump \
--databases \ --databases \
${SCHEMAS[@]} \ ${SCHEMAS[@]} \
${IGNORETABLES[@]} \ ${IGNORETABLES[@]} \
| sed 's/\bCURDATE\b/util.VN_CURDATE/ig'\
| sed 's/\bCURTIME\b/util.VN_CURTIME/ig' \
| sed 's/\bNOW\b/util.VN_NOW/ig' \
| sed 's/\bCURRENT_DATE\b/util.VN_CURDATE/ig' \
| sed 's/\bCURRENT_TIME\b/util.VN_CURTIME/ig' \
| sed 's/\bLOCALTIME\b/util.VN_NOW/ig' \
| sed 's/\bLOCALTIMESTAMP\b/util.VN_NOW/ig' \
| sed 's/ AUTO_INCREMENT=[0-9]* //g' \ | sed 's/ AUTO_INCREMENT=[0-9]* //g' \
> dump/structure.sql > dump/structure.sql

View File

@ -43,7 +43,7 @@ services:
- node.role == worker - node.role == worker
resources: resources:
limits: limits:
memory: 4G memory: 8G
configs: configs:
datasources: datasources:
external: true external: true

View File

@ -218,23 +218,6 @@ let actions = {
return handle.jsonValue(); return handle.jsonValue();
}, },
getValue: async function(selector) {
return await this.waitToGetProperty(selector, 'value');
},
getValues: async function(selectorMap) {
const values = {};
for (const key in selectorMap)
values[key] = await this.waitToGetProperty(selectorMap[key], 'value');
return values;
},
innerText: async function(selector) {
const element = await this.$(selector);
const handle = await element.getProperty('innerText');
return handle.jsonValue();
},
waitPropertyLength: async function(selector, property, minLength) { waitPropertyLength: async function(selector, property, minLength) {
await this.waitForFunction((selector, property, minLength) => { await this.waitForFunction((selector, property, minLength) => {
const element = document.querySelector(selector); const element = document.querySelector(selector);
@ -431,7 +414,7 @@ let actions = {
const selector = 'vn-snackbar .shape.shown'; const selector = 'vn-snackbar .shape.shown';
await this.waitForSelector(selector); await this.waitForSelector(selector);
let message = await this.evaluate(selector => { const message = await this.evaluate(selector => {
const shape = document.querySelector(selector); const shape = document.querySelector(selector);
const message = { const message = {
text: shape.querySelector('.text').innerText text: shape.querySelector('.text').innerText
@ -448,6 +431,8 @@ let actions = {
return message; return message;
}, selector); }, selector);
message.isSuccess = message.type == 'success';
await this.hideSnackbar(); await this.hideSnackbar();
return message; return message;
}, },
@ -483,28 +468,6 @@ let actions = {
}, selector); }, selector);
}, },
clearInput: async function(selector) {
await this.waitForSelector(selector);
let field = await this.evaluate(selector => {
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field;
}, selector);
if ((field != null && field != '') || field == '0') {
let coords = await this.evaluate(selector => {
let rect = document.querySelector(selector).getBoundingClientRect();
return {x: rect.x + (rect.width / 2), y: rect.y + (rect.height / 2), width: rect.width};
}, selector);
await this.mouse.move(coords.x, coords.y);
await this.waitForSelector(`${selector} [icon="clear"]`, {visible: true});
await this.waitToClick(`${selector} [icon="clear"]`);
}
await this.evaluate(selector => {
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field == '';
}, selector);
},
autocompleteSearch: async function(selector, searchValue) { autocompleteSearch: async function(selector, searchValue) {
let builtSelector = await this.selectorFormater(selector); let builtSelector = await this.selectorFormater(selector);
@ -536,9 +499,8 @@ let actions = {
checkboxState: async function(selector) { checkboxState: async function(selector) {
await this.waitForSelector(selector); await this.waitForSelector(selector);
return this.evaluate(selector => { const value = await this.getInputValue(selector);
let checkbox = document.querySelector(selector); switch (value) {
switch (checkbox.$ctrl.field) {
case null: case null:
return 'intermediate'; return 'intermediate';
case true: case true:
@ -546,7 +508,6 @@ let actions = {
default: default:
return 'unchecked'; return 'unchecked';
} }
}, selector);
}, },
isDisabled: async function(selector) { isDisabled: async function(selector) {
@ -639,6 +600,138 @@ let actions = {
waitForContentLoaded: async function() { waitForContentLoaded: async function() {
await this.waitForSpinnerLoad(); await this.waitForSpinnerLoad();
},
async getInputValue(selector) {
return this.evaluate(selector => {
const input = document.querySelector(selector);
return input.$ctrl.field;
}, selector);
},
async getValue(selector) {
return await this.waitToGetProperty(selector, 'value');
},
async innerText(selector) {
const element = await this.$(selector);
const handle = await element.getProperty('innerText');
return handle.jsonValue();
},
async setInput(selector, value) {
const input = await this.$(selector);
const tagName = (await input.evaluate(e => e.tagName)).toLowerCase();
switch (tagName) {
case 'vn-textfield':
case 'vn-datalist':
case 'vn-input-number':
await this.clearInput(selector);
if (value)
await this.write(selector, value.toString());
break;
case 'vn-autocomplete':
if (value)
await this.autocompleteSearch(selector, value.toString());
else
await this.clearInput(selector);
break;
case 'vn-date-picker':
if (value)
await this.pickDate(selector, value);
else
await this.clearInput(selector);
break;
case 'vn-input-time':
if (value)
await this.pickTime(selector, value);
else
await this.clearInput(selector);
break;
case 'vn-check':
for (let i = 0; i < 3; i++) {
if (await this.getInput(selector) == value) break;
await this.click(selector);
}
break;
}
},
async getInput(selector) {
const input = await this.$(selector);
const tagName = (await input.evaluate(e => e.tagName)).toLowerCase();
let el;
let value;
switch (tagName) {
case 'vn-textfield':
case 'vn-autocomplete':
case 'vn-input-time':
case 'vn-datalist':
el = await input.$('input');
value = await el.getProperty('value');
return value.jsonValue();
case 'vn-check':
case 'vn-input-number':
return await this.getInputValue(selector);
case 'vn-textarea':
el = await input.$('textarea');
value = await el.getProperty('value');
return value.jsonValue();
case 'vn-date-picker':
el = await input.$('input');
value = await el.getProperty('value');
if (value) {
const date = new Date(await value.jsonValue());
date.setUTCHours(0, 0, 0, 0);
return date;
} else
return null;
default:
value = await this.innerText(selector);
return value.jsonValue();
}
},
async clearInput(selector) {
await this.waitForSelector(selector);
let field = await this.evaluate(selector => {
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field;
}, selector);
if ((field != null && field != '') || field == '0') {
let coords = await this.evaluate(selector => {
let rect = document.querySelector(selector).getBoundingClientRect();
return {x: rect.x + (rect.width / 2), y: rect.y + (rect.height / 2), width: rect.width};
}, selector);
await this.mouse.move(coords.x, coords.y);
await this.waitForSelector(`${selector} [icon="clear"]`, {visible: true});
await this.waitToClick(`${selector} [icon="clear"]`);
}
await this.evaluate(selector => {
return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field == '';
}, selector);
},
async fetchForm(selector, inputNames) {
const values = {};
for (const inputName of inputNames)
values[inputName] = await this.getInput(`${selector} [vn-name="${inputName}"]`);
return values;
},
async fillForm(selector, values) {
for (const inputName in values)
await this.setInput(`${selector} [vn-name="${inputName}"]`, values[inputName]);
},
async sendForm(selector, values) {
if (values) await this.fillForm(selector, values);
await this.click(`${selector} button[type=submit]`);
return await this.waitForSnackbar();
} }
}; };
@ -646,12 +739,14 @@ export function extendPage(page) {
for (let name in actions) { for (let name in actions) {
page[name] = async(...args) => { page[name] = async(...args) => {
try { try {
return actions[name].apply(page, args); return await actions[name].apply(page, args);
} catch (err) { } catch (err) {
let stringArgs = args let stringArgs = args
.map(i => typeof i == 'function' ? 'Function' : i) .map(i => typeof i == 'function' ? 'Function' : `'${i}'`)
.join(', '); .join(', ');
throw new Error(`.${name}(${stringArgs}): ${err.message}`); const myErr = new Error(`${err.message}\n at Page.${name}(${stringArgs})`);
myErr.stack = err.stack;
throw myErr;
} }
}; };
} }

View File

@ -22,7 +22,8 @@ export async function getBrowser() {
env.E2E_SHOW = true; env.E2E_SHOW = true;
} }
const headless = !env.E2E_SHOW; const headless = env.E2E_SHOW ? false : 'new';
const browser = await Puppeteer.launch({ const browser = await Puppeteer.launch({
args, args,
defaultViewport: null, defaultViewport: null,

View File

@ -193,10 +193,6 @@ export default {
saveNewPoscode: '#savePostcode', saveNewPoscode: '#savePostcode',
createButton: 'vn-client-create button[type=submit]' createButton: 'vn-client-create button[type=submit]'
}, },
clientDescriptor: {
moreMenu: 'vn-client-descriptor vn-icon-button[icon=more_vert]',
simpleTicketButton: '.vn-menu [name="simpleTicket"]'
},
clientBasicData: { clientBasicData: {
name: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.name"]', name: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.name"]',
contact: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.contact"]', contact: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.contact"]',
@ -231,23 +227,6 @@ export default {
saveButton: 'button[type=submit]', saveButton: 'button[type=submit]',
watcher: 'vn-client-fiscal-data vn-watcher' watcher: 'vn-client-fiscal-data vn-watcher'
}, },
clientBillingData: {
payMethod: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]',
IBAN: 'vn-client-billing-data vn-textfield[ng-model="$ctrl.client.iban"]',
dueDay: 'vn-client-billing-data vn-input-number[ng-model="$ctrl.client.dueDay"]',
receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]',
receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]',
receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]',
swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]',
newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button',
newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.name"]',
newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.bic"]',
newBankEntityCountry: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.data.countryFk"]',
newBankEntityCode: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.id"]',
acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]',
saveButton: 'vn-client-billing-data button[type=submit]',
watcher: 'vn-client-billing-data vn-watcher'
},
clientAddresses: { clientAddresses: {
addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]', addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]',
createAddress: 'vn-client-address-index vn-float-button', createAddress: 'vn-client-address-index vn-float-button',
@ -306,21 +285,6 @@ export default {
clientMandate: { clientMandate: {
firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr' firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr'
}, },
clientBalance: {
company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]',
newPaymentButton: `vn-float-button`,
newPaymentBank: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.bankFk"]',
newPaymentAmount: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.amountPaid"]',
newDescription: 'vn-textfield[ng-model="$ctrl.receipt.description"]',
deliveredAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.deliveredAmount"]',
refundAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.amountToReturn"]',
saveButton: '.vn-dialog.shown [response="accept"]',
anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr',
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield',
compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]'
},
webPayment: { webPayment: {
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]', confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]' firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]'
@ -349,7 +313,7 @@ export default {
anyClient: 'vn-client-defaulter tbody > tr', anyClient: 'vn-client-defaulter tbody > tr',
firstClientName: 'vn-client-defaulter tbody > tr:nth-child(1) > td:nth-child(2) > span', firstClientName: 'vn-client-defaulter tbody > tr:nth-child(1) > td:nth-child(2) > span',
firstSalesPersonName: 'vn-client-defaulter tbody > tr:nth-child(1) > td:nth-child(3) > span', firstSalesPersonName: 'vn-client-defaulter tbody > tr:nth-child(1) > td:nth-child(3) > span',
firstObservation: 'vn-client-defaulter tbody > tr:nth-child(1) > td:nth-child(6) > vn-textarea[ng-model="defaulter.observation"]', firstObservation: 'vn-client-defaulter tbody > tr:nth-child(1) > td:nth-child(8) > vn-textarea[ng-model="defaulter.observation"]',
allDefaulterCheckbox: 'vn-client-defaulter thead vn-multi-check', allDefaulterCheckbox: 'vn-client-defaulter thead vn-multi-check',
addObservationButton: 'vn-client-defaulter vn-button[icon="icon-notes"]', addObservationButton: 'vn-client-defaulter vn-button[icon="icon-notes"]',
observation: '.vn-dialog.shown vn-textarea[ng-model="$ctrl.defaulter.observation"]', observation: '.vn-dialog.shown vn-textarea[ng-model="$ctrl.defaulter.observation"]',
@ -466,10 +430,6 @@ export default {
packingOut: 'vn-input-number[ng-model="$ctrl.item.packingOut"]', packingOut: 'vn-input-number[ng-model="$ctrl.item.packingOut"]',
isActiveCheckbox: 'vn-check[label="Active"]', isActiveCheckbox: 'vn-check[label="Active"]',
priceInKgCheckbox: 'vn-check[label="Price in kg"]', priceInKgCheckbox: 'vn-check[label="Price in kg"]',
newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button',
newIntrastatId: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.newIntrastat.intrastatId"]',
newIntrastatDescription: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newIntrastat.description"]',
acceptIntrastatButton: '.vn-dialog.shown button[response="accept"]',
submitBasicDataButton: `button[type=submit]` submitBasicDataButton: `button[type=submit]`
}, },
itemTags: { itemTags: {
@ -622,13 +582,6 @@ export default {
saveButton: '.vn-dialog.shown [response="accept"]', saveButton: '.vn-dialog.shown [response="accept"]',
expeditionRow: 'vn-ticket-expedition vn-table vn-tbody > vn-tr' expeditionRow: 'vn-ticket-expedition vn-table vn-tbody > vn-tr'
}, },
ticketPackages: {
firstPackage: 'vn-autocomplete[label="Package"]',
firstQuantity: 'vn-ticket-package vn-horizontal:nth-child(1) vn-input-number[ng-model="package.quantity"]',
firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]',
addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]',
savePackagesButton: `button[type=submit]`
},
ticketSales: { ticketSales: {
setOk: 'vn-ticket-sale vn-tool-bar > vn-button[label="Ok"] > button', setOk: 'vn-ticket-sale vn-tool-bar > vn-button[label="Ok"] > button',
saleLine: 'vn-table div > vn-tbody > vn-tr vn-check', saleLine: 'vn-table div > vn-tbody > vn-tr vn-check',
@ -642,6 +595,8 @@ export default {
moreMenuUpdateDiscount: 'vn-item[name="discount"]', moreMenuUpdateDiscount: 'vn-item[name="discount"]',
moreMenuRecalculatePrice: 'vn-item[name="calculatePrice"]', moreMenuRecalculatePrice: 'vn-item[name="calculatePrice"]',
moreMenuRefund: 'vn-item[name="refund"]', moreMenuRefund: 'vn-item[name="refund"]',
refundWithWarehouse: 'vn-item[name="refundWithWarehouse"]',
refundWithoutWarehouse: 'vn-item[name="refundWithoutWarehouse"]',
moreMenuUpdateDiscountInput: 'vn-input-number[ng-model="$ctrl.edit.discount"] input', moreMenuUpdateDiscountInput: 'vn-input-number[ng-model="$ctrl.edit.discount"] input',
transferQuantityInput: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable > span > text', transferQuantityInput: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable > span > text',
transferQuantityCell: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable', transferQuantityCell: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable',
@ -672,6 +627,7 @@ export default {
selectAllSalesCheckbox: 'vn-ticket-sale vn-thead vn-check', selectAllSalesCheckbox: 'vn-ticket-sale vn-thead vn-check',
secondSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(2) vn-check[ng-model="sale.checked"]', secondSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(2) vn-check[ng-model="sale.checked"]',
thirdSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(3) vn-check[ng-model="sale.checked"]', thirdSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(3) vn-check[ng-model="sale.checked"]',
fourthSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(4) vn-check[ng-model="sale.checked"]',
deleteSaleButton: 'vn-ticket-sale vn-tool-bar > vn-button[icon="delete"]', deleteSaleButton: 'vn-ticket-sale vn-tool-bar > vn-button[icon="delete"]',
transferSaleButton: 'vn-ticket-sale vn-tool-bar > vn-button[icon="call_split"]', transferSaleButton: 'vn-ticket-sale vn-tool-bar > vn-button[icon="call_split"]',
moveToTicketInput: 'form vn-input-number[ng-model="$ctrl.transfer.ticketId"] input', moveToTicketInput: 'form vn-input-number[ng-model="$ctrl.transfer.ticketId"] input',
@ -873,15 +829,6 @@ export default {
landedDatePicker: 'vn-date-picker[label="Landed"]', landedDatePicker: 'vn-date-picker[label="Landed"]',
createButton: 'button[type=submit]' createButton: 'button[type=submit]'
}, },
orderSummary: {
id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span',
alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span',
consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(6) span',
subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)',
vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)',
total: 'vn-order-summary vn-one.taxes > p:nth-child(3)',
sale: 'vn-order-summary vn-tbody > vn-tr',
},
orderCatalog: { orderCatalog: {
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]', plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]', type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]',
@ -899,14 +846,6 @@ export default {
fifthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(5) vn-icon[icon=cancel]', fifthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(5) vn-icon[icon=cancel]',
sixthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(6) vn-icon[icon=cancel]', sixthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(6) vn-icon[icon=cancel]',
}, },
orderBasicData: {
client: 'vn-autocomplete[label="Client"]',
address: 'vn-autocomplete[label="Address"]',
agency: 'vn-autocomplete[label="Agency"]',
observation: 'vn-textarea[label="Notes"]',
saveButton: `button[type=submit]`,
acceptButton: '.vn-confirm.shown button[response="accept"]'
},
orderLine: { orderLine: {
orderSubtotal: 'vn-order-line .header :first-child', orderSubtotal: 'vn-order-line .header :first-child',
firstLineDeleteButton: 'vn-order-line vn-tbody > vn-tr:nth-child(1) vn-icon[icon="delete"]', firstLineDeleteButton: 'vn-order-line vn-tbody > vn-tr:nth-child(1) vn-icon[icon="delete"]',
@ -946,16 +885,6 @@ export default {
goToRouteSummaryButton: 'vn-route-summary > vn-card > h5 > a', goToRouteSummaryButton: 'vn-route-summary > vn-card > h5 > a',
}, },
routeBasicData: {
worker: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
vehicle: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.vehicleFk"]',
kmStart: 'vn-route-basic-data vn-input-number[ng-model="$ctrl.route.kmStart"]',
kmEnd: 'vn-route-basic-data vn-input-number[ng-model="$ctrl.route.kmEnd"]',
createdDate: 'vn-route-basic-data vn-date-picker[ng-model="$ctrl.route.created"]',
startedHour: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.started"]',
finishedHour: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.finished"]',
saveButton: 'vn-route-basic-data button[type=submit]'
},
routeTickets: { routeTickets: {
firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-input-number[ng-model="ticket.priority"]', firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-input-number[ng-model="ticket.priority"]',
firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check', firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check',
@ -1240,22 +1169,6 @@ export default {
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]', confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
anyBuyLine: 'vn-entry-summary tr.dark-row' anyBuyLine: 'vn-entry-summary tr.dark-row'
}, },
entryBasicData: {
reference: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.reference"]',
invoiceNumber: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.invoiceNumber"]',
notes: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.notes"]',
observations: 'vn-entry-basic-data vn-textarea[ng-model="$ctrl.entry.observation"]',
supplier: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]',
currency: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.currencyFk"]',
commission: 'vn-entry-basic-data vn-input-number[ng-model="$ctrl.entry.commission"]',
company: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.companyFk"]',
ordered: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isOrdered"]',
confirmed: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isConfirmed"]',
inventory: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isExcludedFromAvailable"]',
raid: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isRaid"]',
booked: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isBooked"]',
save: 'vn-entry-basic-data button[type=submit]',
},
entryDescriptor: { entryDescriptor: {
agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(1) span', agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(1) span',
travelsQuicklink: 'vn-entry-descriptor vn-quick-link[icon="local_airport"] > a', travelsQuicklink: 'vn-entry-descriptor vn-quick-link[icon="local_airport"] > a',

View File

@ -15,81 +15,55 @@ describe('SmartTable SearchBar integration', () => {
await browser.close(); await browser.close();
}); });
describe('as filters in smart-table section', () => { it('should search by type in searchBar, reload page and have same results', async() => {
it('should search by type in searchBar', async() => {
await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton); await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton);
await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium'); await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium');
await page.waitToClick(selectors.itemsIndex.advancedSearchButton); await page.waitToClick(selectors.itemsIndex.advancedSearchButton);
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3);
});
it('should reload page and have same results', async() => {
await page.reload({ await page.reload({
waitUntil: 'networkidle2' waitUntil: 'networkidle2'
}); });
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3);
});
it('should search by grouping in smartTable', async() => {
await page.waitToClick(selectors.itemsIndex.advancedSmartTableButton); await page.waitToClick(selectors.itemsIndex.advancedSmartTableButton);
await page.write(selectors.itemsIndex.advancedSmartTableGrouping, '1'); await page.write(selectors.itemsIndex.advancedSmartTableGrouping, '1');
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2);
});
it('should now reload page and have same results', async() => {
await page.reload({ await page.reload({
waitUntil: 'networkidle2' waitUntil: 'networkidle2'
}); });
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2);
}); });
});
describe('as filters in section without smart-table', () => { it('should filter in section without smart-table and search in searchBar go to zone section', async() => {
it('go to zone section', async() => {
await page.loginAndModule('salesPerson', 'zone'); await page.loginAndModule('salesPerson', 'zone');
await page.waitToClick(selectors.globalItems.searchButton); await page.waitToClick(selectors.globalItems.searchButton);
});
it('should search in searchBar first time', async() => {
await page.doSearch('A'); await page.doSearch('A');
const count = await page.countElement(selectors.zoneIndex.searchResult); const firstCount = await page.countElement(selectors.zoneIndex.searchResult);
expect(count).toEqual(7);
});
it('should search in searchBar second time', async() => {
await page.doSearch('A'); await page.doSearch('A');
const count = await page.countElement(selectors.zoneIndex.searchResult); const secondCount = await page.countElement(selectors.zoneIndex.searchResult);
expect(count).toEqual(7); expect(firstCount).toEqual(7);
expect(secondCount).toEqual(7);
}); });
it('should search in searchBar third time', async() => { it('should order orders by first id and order by last id, reload page and have same order', async() => {
await page.doSearch('A');
const count = await page.countElement(selectors.zoneIndex.searchResult);
expect(count).toEqual(7);
});
});
describe('as orders', () => {
it('should order by first id', async() => {
await page.loginAndModule('developer', 'item'); await page.loginAndModule('developer', 'item');
await page.accessToSection('item.fixedPrice'); await page.accessToSection('item.fixedPrice');
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '1'); await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '1');
});
it('should order by last id, reload page and have same order', async() => {
await page.waitToClick(selectors.itemFixedPrice.orderColumnId); await page.waitToClick(selectors.itemFixedPrice.orderColumnId);
await page.reload({ await page.reload({
waitUntil: 'networkidle2' waitUntil: 'networkidle2'
}); });
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '13'); await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '3');
});
}); });
}); });

View File

@ -171,100 +171,40 @@ describe('Client Edit fiscalData path', () => {
expect(result).toEqual('SMASH'); expect(result).toEqual('SMASH');
}); });
it('should confirm the fiscal id have been edited', async() => { it('should confirm the fiscal data have been edited', async() => {
const result = await page.waitToGetProperty(selectors.clientFiscalData.fiscalId, 'value'); const fiscalId = await page.waitToGetProperty(selectors.clientFiscalData.fiscalId, 'value');
const address = await page.waitToGetProperty(selectors.clientFiscalData.address, 'value');
const postcode = await page.waitToGetProperty(selectors.clientFiscalData.postcode, 'value');
const sageTax = await page.waitToGetProperty(selectors.clientFiscalData.sageTax, 'value');
const sageTransaction = await page.waitToGetProperty(selectors.clientFiscalData.sageTransaction, 'value');
const city = await page.waitToGetProperty(selectors.clientFiscalData.city, 'value');
const province = await page.waitToGetProperty(selectors.clientFiscalData.province, 'value');
const country = await page.waitToGetProperty(selectors.clientFiscalData.country, 'value');
const active = await page.checkboxState(selectors.clientFiscalData.activeCheckbox);
const frozen = await page.checkboxState(selectors.clientFiscalData.frozenCheckbox);
const hasToInvoice = await page.checkboxState(selectors.clientFiscalData.hasToInvoiceCheckbox);
const vies = await page.checkboxState(selectors.clientFiscalData.viesCheckbox);
const notifyByMail = await page.checkboxState(selectors.clientFiscalData.notifyByMailCheckbox);
const invoiceByAddress = await page.checkboxState(selectors.clientFiscalData.invoiceByAddressCheckbox);
const equalizationTax = await page.checkboxState(selectors.clientFiscalData.equalizationTaxCheckbox);
const verifiedData = await page.checkboxState(selectors.clientFiscalData.verifiedDataCheckbox);
expect(result).toEqual('94980061C'); expect(fiscalId).toEqual('94980061C');
}); expect(address).toEqual('Somewhere edited');
expect(postcode).toContain('46000');
it('should confirm the address have been edited', async() => { expect(sageTax).toEqual('Operaciones no sujetas');
const result = await page.waitToGetProperty(selectors.clientFiscalData.address, 'value'); expect(sageTransaction).toEqual('Regularización de inversiones');
expect(city).toEqual('Valencia');
expect(result).toEqual('Somewhere edited'); expect(province).toContain('Province one');
}); expect(country).toEqual('España');
expect(active).toBe('unchecked');
it('should confirm the postcode have been edited', async() => { expect(frozen).toBe('checked');
const result = await page.waitToGetProperty(selectors.clientFiscalData.postcode, 'value'); expect(hasToInvoice).toBe('unchecked');
expect(vies).toBe('checked');
expect(result).toContain('46000'); expect(notifyByMail).toBe('unchecked');
}); expect(invoiceByAddress).toBe('checked');
expect(equalizationTax).toBe('unchecked');
it('should confirm the sageTax have been edited', async() => { expect(verifiedData).toBe('checked');
const result = await page.waitToGetProperty(selectors.clientFiscalData.sageTax, 'value');
expect(result).toEqual('Operaciones no sujetas');
});
it('should confirm the sageTransaction have been edited', async() => {
const result = await page.waitToGetProperty(selectors.clientFiscalData.sageTransaction, 'value');
expect(result).toEqual('36: Regularización de inversiones');
});
it('should confirm the city have been autocompleted', async() => {
const result = await page.waitToGetProperty(selectors.clientFiscalData.city, 'value');
expect(result).toEqual('Valencia');
});
it(`should confirm the province have been autocompleted`, async() => {
const result = await page.waitToGetProperty(selectors.clientFiscalData.province, 'value');
expect(result).toContain('Province one');
});
it('should confirm the country have been autocompleted', async() => {
const result = await page.waitToGetProperty(selectors.clientFiscalData.country, 'value');
expect(result).toEqual('España');
});
it('should confirm active checkbox is unchecked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.activeCheckbox);
expect(result).toBe('unchecked');
});
it('should confirm frozen checkbox is checked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.frozenCheckbox);
expect(result).toBe('checked');
});
it('should confirm Has to invoice checkbox is unchecked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.hasToInvoiceCheckbox);
expect(result).toBe('unchecked');
});
it('should confirm Vies checkbox is checked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.viesCheckbox);
expect(result).toBe('checked');
});
it('should confirm Notify by email checkbox is unchecked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.notifyByMailCheckbox);
expect(result).toBe('unchecked');
});
it('should confirm invoice by address checkbox is checked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.invoiceByAddressCheckbox);
expect(result).toBe('checked');
});
it('should confirm Equalization tax checkbox is unchecked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.equalizationTaxCheckbox);
expect(result).toBe('unchecked');
});
it('should confirm Verified data checkbox is checked', async() => {
const result = await page.checkboxState(selectors.clientFiscalData.verifiedDataCheckbox);
expect(result).toBe('checked');
}); });
// confirm invoice by address checkbox gets checked if the EQtax differs between addresses step 1 // confirm invoice by address checkbox gets checked if the EQtax differs between addresses step 1

View File

@ -1,6 +1,23 @@
import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
payMethod: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]',
IBAN: 'vn-client-billing-data vn-textfield[ng-model="$ctrl.client.iban"]',
dueDay: 'vn-client-billing-data vn-input-number[ng-model="$ctrl.client.dueDay"]',
receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]',
receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]',
receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]',
swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]',
newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button',
newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.name"]',
newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.bic"]',
newBankEntityCountry: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.data.countryFk"]',
newBankEntityCode: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.id"]',
acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]',
saveButton: 'vn-client-billing-data button[type=submit]',
watcher: 'vn-client-billing-data vn-watcher'
};
describe('Client Edit billing data path', () => { describe('Client Edit billing data path', () => {
let browser; let browser;
let page; let page;
@ -17,93 +34,72 @@ describe('Client Edit billing data path', () => {
}); });
it(`should attempt to edit the billing data without an IBAN but fail`, async() => { it(`should attempt to edit the billing data without an IBAN but fail`, async() => {
await page.autocompleteSearch(selectors.clientBillingData.payMethod, 'PayMethod with IBAN'); await page.autocompleteSearch($.payMethod, 'PayMethod with IBAN');
await page.autocompleteSearch(selectors.clientBillingData.swiftBic, 'BBKKESMMMMM'); await page.autocompleteSearch($.swiftBic, 'BBKKESMMMMM');
await page.clearInput(selectors.clientBillingData.dueDay); await page.clearInput($.dueDay);
await page.write(selectors.clientBillingData.dueDay, '60'); await page.write($.dueDay, '60');
await page.waitForTextInField(selectors.clientBillingData.dueDay, '60'); await page.waitForTextInField($.dueDay, '60');
await page.waitToClick(selectors.clientBillingData.receivedCoreLCRCheckbox); await page.waitToClick($.receivedCoreLCRCheckbox);
await page.waitToClick(selectors.clientBillingData.receivedCoreVNLCheckbox); await page.waitToClick($.receivedCoreVNLCheckbox);
await page.waitToClick(selectors.clientBillingData.receivedB2BVNLCheckbox); await page.waitToClick($.receivedB2BVNLCheckbox);
await page.waitToClick(selectors.clientBillingData.saveButton); await page.waitToClick($.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('That payment method requires an IBAN'); expect(message.text).toContain('That payment method requires an IBAN');
}); });
it(`should create a new BIC code`, async() => { it(`should create a new BIC code`, async() => {
await page.waitToClick(selectors.clientBillingData.newBankEntityButton); await page.waitToClick($.newBankEntityButton);
await page.write(selectors.clientBillingData.newBankEntityName, 'Gotham City Bank'); await page.write($.newBankEntityName, 'Gotham City Bank');
await page.write(selectors.clientBillingData.newBankEntityBIC, 'GTHMCT'); await page.write($.newBankEntityBIC, 'GTHMCT');
await page.autocompleteSearch(selectors.clientBillingData.newBankEntityCountry, 'España'); await page.autocompleteSearch($.newBankEntityCountry, 'España');
await page.write(selectors.clientBillingData.newBankEntityCode, '9999'); await page.write($.newBankEntityCode, '9999');
await page.waitToClick(selectors.clientBillingData.acceptBankEntityButton); await page.waitToClick($.acceptBankEntityButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
await page.waitForTextInField(selectors.clientBillingData.swiftBic, 'Gotham City Bank'); await page.waitForTextInField($.swiftBic, 'GTHMCT');
const newcode = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value'); const newcode = await page.waitToGetProperty($.swiftBic, 'value');
expect(newcode).toEqual('GTHMCT Gotham City Bank');
expect(newcode).toEqual('GTHMCT');
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');
}); });
it(`should confirm the IBAN pay method was sucessfully saved`, async() => { it(`should confirm the IBAN pay method was sucessfully saved`, async() => {
const payMethod = await page.waitToGetProperty(selectors.clientBillingData.payMethod, 'value'); const payMethod = await page.waitToGetProperty($.payMethod, 'value');
expect(payMethod).toEqual('PayMethod with IBAN'); expect(payMethod).toEqual('PayMethod with IBAN');
}); });
it(`should clear the BIC code field, update the IBAN to see how he BIC code autocompletes`, async() => { it(`should clear the BIC code field, update the IBAN to see how he BIC code autocompletes`, async() => {
await page.write(selectors.clientBillingData.IBAN, 'ES9121000418450200051332'); await page.write($.IBAN, 'ES9121000418450200051332');
await page.keyboard.press('Tab'); await page.keyboard.press('Tab');
await page.keyboard.press('Tab'); await page.keyboard.press('Tab');
await page.waitForTextInField(selectors.clientBillingData.swiftBic, 'caixesbb'); await page.waitForTextInField($.swiftBic, 'caixesbb');
let automaticCode = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value'); let automaticCode = await page.waitToGetProperty($.swiftBic, 'value');
expect(automaticCode).toEqual('CAIXESBB Caixa Bank'); expect(automaticCode).toEqual('CAIXESBB');
}); });
it(`should save the form with all its new data`, async() => { it(`should save the form with all its new data`, async() => {
await page.waitForWatcherData(selectors.clientBillingData.watcher); await page.waitForWatcherData($.watcher);
await page.waitToClick(selectors.clientBillingData.saveButton); await page.waitToClick($.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Notification sent!'); expect(message.text).toContain('Notification sent!');
}); });
it('should confirm the due day have been edited', async() => { it('should confirm the billing data have been edited', async() => {
const dueDate = await page.waitToGetProperty(selectors.clientBillingData.dueDay, 'value'); const dueDate = await page.waitToGetProperty($.dueDay, 'value');
const IBAN = await page.waitToGetProperty($.IBAN, 'value');
const swiftBic = await page.waitToGetProperty($.swiftBic, 'value');
const receivedCoreLCR = await page.checkboxState($.receivedCoreLCRCheckbox);
const receivedCoreVNL = await page.checkboxState($.receivedCoreVNLCheckbox);
const receivedB2BVNL = await page.checkboxState($.receivedB2BVNLCheckbox);
expect(dueDate).toEqual('60'); expect(dueDate).toEqual('60');
});
it('should confirm the IBAN was saved', async() => {
const IBAN = await page.waitToGetProperty(selectors.clientBillingData.IBAN, 'value');
expect(IBAN).toEqual('ES9121000418450200051332'); expect(IBAN).toEqual('ES9121000418450200051332');
}); expect(swiftBic).toEqual('CAIXESBB');
expect(receivedCoreLCR).toBe('checked');
it('should confirm the swift / BIC code was saved', async() => { expect(receivedCoreVNL).toBe('unchecked');
const code = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value'); expect(receivedB2BVNL).toBe('unchecked');
expect(code).toEqual('CAIXESBB Caixa Bank');
});
it('should confirm Received LCR checkbox is checked', async() => {
const result = await page.checkboxState(selectors.clientBillingData.receivedCoreLCRCheckbox);
expect(result).toBe('checked');
});
it('should confirm Received core VNL checkbox is unchecked', async() => {
const result = await page.checkboxState(selectors.clientBillingData.receivedCoreVNLCheckbox);
expect(result).toBe('unchecked');
});
it('should confirm Received B2B VNL checkbox is unchecked', async() => {
const result = await page.checkboxState(selectors.clientBillingData.receivedB2BVNLCheckbox);
expect(result).toBe('unchecked');
}); });
}); });

View File

@ -5,8 +5,8 @@ const $ = {
userName: 'vn-client-web-access vn-textfield[ng-model="$ctrl.account.name"]', userName: 'vn-client-web-access vn-textfield[ng-model="$ctrl.account.name"]',
email: 'vn-client-web-access vn-textfield[ng-model="$ctrl.account.email"]', email: 'vn-client-web-access vn-textfield[ng-model="$ctrl.account.email"]',
saveButton: 'vn-client-web-access button[type=submit]', saveButton: 'vn-client-web-access button[type=submit]',
nameValue: 'vn-client-log .change:nth-child(1) .basic-json:nth-child(1) vn-json-value', nameValue: 'vn-client-log .change:nth-child(1) .basic-json:nth-child(2) vn-json-value',
activeValue: 'vn-client-log .change:nth-child(2) .basic-json:nth-child(2) vn-json-value' activeValue: 'vn-client-log .change:nth-child(2) .basic-json:nth-child(1) vn-json-value'
}; };
describe('Client web access path', () => { describe('Client web access path', () => {

View File

@ -29,19 +29,16 @@ describe('Client Add greuge path', () => {
expect(message.text).toContain('Some fields are invalid'); expect(message.text).toContain('Some fields are invalid');
}); });
it(`should create a new greuge with all its data`, async() => { it(`should create a new greuge with all its data and confirm the greuge was added to the list`, async() => {
await page.write(selectors.clientGreuge.amount, '999'); await page.write(selectors.clientGreuge.amount, '999');
await page.waitForTextInField(selectors.clientGreuge.amount, '999'); await page.waitForTextInField(selectors.clientGreuge.amount, '999');
await page.write(selectors.clientGreuge.description, 'new armor for Batman!'); await page.write(selectors.clientGreuge.description, 'new armor for Batman!');
await page.waitToClick(selectors.clientGreuge.saveButton); await page.waitToClick(selectors.clientGreuge.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should confirm the greuge was added to the list', async() => {
const result = await page.waitToGetProperty(selectors.clientGreuge.firstGreugeText, 'innerText'); const result = await page.waitToGetProperty(selectors.clientGreuge.firstGreugeText, 'innerText');
expect(message.text).toContain('Data saved!');
expect(result).toContain(999); expect(result).toContain(999);
expect(result).toContain('new armor for Batman!'); expect(result).toContain('new armor for Batman!');
expect(result).toContain('Diff'); expect(result).toContain('Diff');

View File

@ -1,6 +1,17 @@
import selectors from '../../helpers/selectors'; import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]',
newPaymentButton: `vn-float-button`,
newPayment: '.vn-dialog.shown',
refundAmount: '.vn-dialog.shown [vn-name="amountToReturn"]',
saveButton: '.vn-dialog.shown [response="accept"]',
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable vn-textfield',
};
describe('Client balance path', () => { describe('Client balance path', () => {
let browser; let browser;
let page; let page;
@ -18,125 +29,100 @@ describe('Client balance path', () => {
it('should now edit the local user config data', async() => { it('should now edit the local user config data', async() => {
await page.waitToClick(selectors.globalItems.userMenuButton); await page.waitToClick(selectors.globalItems.userMenuButton);
await page.autocompleteSearch(selectors.globalItems.userLocalCompany, 'CCs'); await page.autocompleteSearch(selectors.globalItems.userLocalCompany, 'CCs');
const message = await page.waitForSnackbar(); const companyMessage = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should access to the balance section to check the data shown matches the local settings', async() => {
await page.accessToSection('client.card.balance.index'); await page.accessToSection('client.card.balance.index');
let result = await page.waitToGetProperty(selectors.clientBalance.company, 'value'); const company = await page.getValue($.company);
expect(result).toEqual('CCs');
});
it('should now clear the user local settings', async() => {
await page.waitToClick(selectors.globalItems.userMenuButton); await page.waitToClick(selectors.globalItems.userMenuButton);
await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete); await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should reload the section', async() => {
await page.closePopup(); await page.closePopup();
await page.reloadSection('client.card.balance.index'); await page.reloadSection('client.card.balance.index');
expect(companyMessage.isSuccess).toBeTrue();
expect(company).toEqual('CCs');
expect(message.isSuccess).toBeTrue();
}); });
it('should create a new payment that clears the debt', async() => { it('should create a new payment that clears the debt', async() => {
await page.closePopup(); await page.waitToClick($.newPaymentButton);
await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.fillForm($.newPayment, {
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); bank: 'Cash',
await page.clearInput(selectors.clientBalance.newDescription); description: 'Description',
await page.write(selectors.clientBalance.newDescription, 'Description'); viewReceipt: false
await page.waitToClick(selectors.clientBalance.saveButton); });
await page.respondToDialog('accept');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.isSuccess).toBeTrue();
}); });
it('should edit the 1st line reference', async() => { it('should edit the 1st line reference and check data', async() => {
await page.waitToClick(selectors.clientBalance.firstLineReference); await page.waitToClick($.firstLineReference);
await page.write(selectors.clientBalance.firstLineReferenceInput, 'Miscellaneous payment'); await page.write($.firstLineReferenceInput, 'Miscellaneous payment');
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should check balance is now 0, the reference was saved and the company is now VNL becouse the user local settings were removed', async() => {
await page.waitForSpinnerLoad(); await page.waitForSpinnerLoad();
let company = await page let company = await page.getValue($.company);
.waitToGetProperty(selectors.clientBalance.company, 'value'); let reference = await page.innerText($.firstLineReference);
let firstBalanceLine = await page.innerText($.firstLineBalance);
let reference = await page
.waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText');
let firstBalanceLine = await page
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
expect(message.isSuccess).toBeTrue();
expect(company).toEqual('VNL'); expect(company).toEqual('VNL');
expect(reference).toEqual('Miscellaneous payment'); expect(reference).toEqual('Miscellaneous payment');
expect(firstBalanceLine).toContain('0.00'); expect(firstBalanceLine).toContain('0.00');
}); });
it('should create a new payment and check the cash comparison works correctly', async() => { it('should create a new payment, check the cash comparison works correctly and balance value is -100', async() => {
const amountPaid = '100'; await page.waitToClick($.newPaymentButton);
const cashHanded = '500'; await page.fillForm($.newPayment, {
const expectedRefund = '400'; amountPaid: 100,
description: 'Payment',
await page.waitToClick(selectors.clientBalance.newPaymentButton); deliveredAmount: 500,
await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); viewReceipt: false
await page.clearInput(selectors.clientBalance.newDescription); });
await page.write(selectors.clientBalance.newDescription, 'Payment'); const refund = await page.getValue($.refundAmount);
await page.write(selectors.clientBalance.deliveredAmount, cashHanded); await page.respondToDialog('accept');
const refund = await page.waitToGetProperty(selectors.clientBalance.refundAmount, 'value');
await page.waitToClick(selectors.clientBalance.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(refund).toEqual(expectedRefund); const result = await page.innerText($.firstLineBalance);
expect(message.text).toContain('Data saved!');
});
it('should check the balance value is now -100', async() => {
let result = await page
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
expect(refund).toEqual('400');
expect(message.isSuccess).toBeTrue();
expect(result).toContain('-€100.00'); expect(result).toContain('-€100.00');
}); });
it('should create a new payment and check the cash exceeded the maximum', async() => { it('should create a new payment and check the cash exceeded the maximum', async() => {
const amountPaid = '1001'; await page.waitToClick($.newPaymentButton);
await page.fillForm($.newPayment, {
await page.closePopup(); bank: 'Cash',
await page.waitToClick(selectors.clientBalance.newPaymentButton); amountPaid: 1001,
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); description: 'Payment'
await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); });
await page.clearInput(selectors.clientBalance.newDescription); await page.waitToClick($.saveButton);
await page.write(selectors.clientBalance.newDescription, 'Payment');
await page.waitToClick(selectors.clientBalance.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Amount exceeded'); expect(message.text).toContain('Amount exceeded');
}); });
it('should create a new payment that sets the balance back to the original negative value', async() => { it('should create a new payment that sets the balance back to negative value and check it', async() => {
await page.closePopup(); await page.closePopup();
await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.waitToClick($.newPaymentButton);
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt');
await page.overwrite(selectors.clientBalance.newPaymentAmount, '-150'); await page.fillForm($.newPayment, {
await page.clearInput(selectors.clientBalance.newDescription); bank: 'Pay on receipt',
await page.write(selectors.clientBalance.newDescription, 'Description'); amountPaid: -150,
await page.waitToClick(selectors.clientBalance.saveButton); description: 'Description'
});
await page.respondToDialog('accept');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); const result = await page.innerText($.firstLineBalance);
});
it('should check balance is now 50', async() => {
let result = await page
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
expect(message.isSuccess).toBeTrue();
expect(result).toEqual('€50.00'); expect(result).toEqual('€50.00');
}); });
@ -149,12 +135,9 @@ describe('Client balance path', () => {
await page.waitForState('client.index'); await page.waitForState('client.index');
}); });
it('should now search for the user Petter Parker', async() => { it('should now search for the user Petter Parker not check the payment button is not present', async() => {
await page.accessToSearchResult('Petter Parker'); await page.accessToSearchResult('Petter Parker');
await page.accessToSection('client.card.balance.index'); await page.accessToSection('client.card.balance.index');
}); await page.waitForSelector($.newPaymentButton, {hidden: true});
it('should not be able to click the new payment button as it isnt present', async() => {
await page.waitForSelector(selectors.clientBalance.newPaymentButton, {hidden: true});
}); });
}); });

View File

@ -1,6 +1,11 @@
import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]',
compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]',
saveButton: '.vn-dialog.shown [response="accept"]'
};
describe('Client Send balance compensation', () => { describe('Client Send balance compensation', () => {
let browser; let browser;
let page; let page;
@ -17,9 +22,9 @@ describe('Client Send balance compensation', () => {
}); });
it(`should click on send compensation button`, async() => { it(`should click on send compensation button`, async() => {
await page.autocompleteSearch(selectors.clientBalance.company, 'VNL'); await page.autocompleteSearch($.company, 'VNL');
await page.waitToClick(selectors.clientBalance.compensationButton); await page.waitToClick($.compensationButton);
await page.waitToClick(selectors.clientBalance.saveButton); await page.waitToClick($.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Notification sent!'); expect(message.text).toContain('Notification sent!');

View File

@ -1,14 +1,23 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
form: 'vn-item-basic-data form',
intrastatForm: '.vn-dialog.shown form',
newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button'
};
describe('Item Edit basic data path', () => { describe('Item Edit basic data path', () => {
let browser; let browser;
let page; let page;
beforeAll(async() => { beforeAll(async() => {
browser = await getBrowser(); browser = await getBrowser();
page = browser.page; page = browser.page;
await page.loginAndModule('buyer', 'item'); await page.loginAndModule('buyer', 'item');
await page.accessToSearchResult('Melee weapon combat fist 15cm'); await page.accessToSearchResult('Melee weapon combat fist 15cm');
});
beforeEach(async() => {
await page.accessToSection('item.card.basicData'); await page.accessToSection('item.card.basicData');
}); });
@ -16,124 +25,43 @@ describe('Item Edit basic data path', () => {
await browser.close(); await browser.close();
}); });
it(`should check the descritor edit button is visible for buyer`, async() => { it(`should edit the item basic data and confirm the item data was edited`, async() => {
await page.waitForSelector(selectors.itemDescriptor.editButton, {visible: true}); const values = {
}); name: 'Rose of Purity',
longName: 'RS Rose of Purity',
type: 'Anthurium',
intrastat: 'Coral y materiales similares',
origin: 'Spain',
relevancy: 1,
generic: 'Pallet',
isActive: false,
priceInKg: true,
isFragile: true,
packingOut: 5
};
it(`should edit the item basic data`, async() => { const message = await page.sendForm($.form, values);
await page.clearInput(selectors.itemBasicData.name);
await page.write(selectors.itemBasicData.name, 'Rose of Purity');
await page.clearInput(selectors.itemBasicData.longName);
await page.write(selectors.itemBasicData.longName, 'RS Rose of Purity');
await page.autocompleteSearch(selectors.itemBasicData.type, 'Anthurium');
await page.autocompleteSearch(selectors.itemBasicData.intrastat, 'Coral y materiales similares');
await page.autocompleteSearch(selectors.itemBasicData.origin, 'Spain');
await page.clearInput(selectors.itemBasicData.relevancy);
await page.write(selectors.itemBasicData.relevancy, '1');
await page.clearInput(selectors.itemBasicData.generic);
await page.autocompleteSearch(selectors.itemBasicData.generic, '16');
await page.waitToClick(selectors.itemBasicData.isActiveCheckbox);
await page.waitToClick(selectors.itemBasicData.priceInKgCheckbox);
await page.waitToClick(selectors.itemBasicData.isFragile);
await page.write(selectors.itemBasicData.packingOut, '5');
await page.waitToClick(selectors.itemBasicData.submitBasicDataButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it(`should create a new intrastat`, async() => {
await page.waitToClick(selectors.itemBasicData.newIntrastatButton);
await page.write(selectors.itemBasicData.newIntrastatId, '588420239');
await page.write(selectors.itemBasicData.newIntrastatDescription, 'Tropical Flowers');
await page.waitToClick(selectors.itemBasicData.acceptIntrastatButton);
await page.waitForTextInField(selectors.itemBasicData.intrastat, 'Tropical Flowers');
let newcode = await page.waitToGetProperty(selectors.itemBasicData.intrastat, 'value');
expect(newcode).toEqual('588420239 Tropical Flowers');
});
it('should save with the new intrastat', async() => {
await page.waitToClick(selectors.itemBasicData.submitBasicDataButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it(`should confirm the item name was edited`, async() => {
await page.reloadSection('item.card.basicData'); await page.reloadSection('item.card.basicData');
const result = await page.waitToGetProperty(selectors.itemBasicData.name, 'value'); const formValues = await page.fetchForm($.form, Object.keys(values));
expect(result).toEqual('Rose of Purity'); expect(message.isSuccess).toBeTrue();
expect(formValues).toEqual(values);
}); });
it(`should confirm the item type was edited`, async() => { it(`should create a new intrastat and save it`, async() => {
const result = await page await page.click($.newIntrastatButton);
.waitToGetProperty(selectors.itemBasicData.type, 'value'); await page.waitForSelector($.intrastatForm);
await page.fillForm($.intrastatForm, {
expect(result).toEqual('Anthurium'); id: '588420239',
description: 'Tropical Flowers'
}); });
await page.respondToDialog('accept');
it(`should confirm the item intrastat was edited`, async() => { const message = await page.sendForm($.form);
const result = await page await page.reloadSection('item.card.basicData');
.waitToGetProperty(selectors.itemBasicData.intrastat, 'value'); const formValues = await page.fetchForm($.form, ['intrastat']);
expect(result).toEqual('588420239 Tropical Flowers'); expect(message.isSuccess).toBeTrue();
}); expect(formValues).toEqual({intrastat: 'Tropical Flowers'});
it(`should confirm the item relevancy was edited`, async() => {
const result = await page
.waitToGetProperty(selectors.itemBasicData.relevancy, 'value');
expect(result).toEqual('1');
});
it(`should confirm the item origin was edited`, async() => {
const result = await page
.waitToGetProperty(selectors.itemBasicData.origin, 'value');
expect(result).toEqual('Spain');
});
it(`should confirm the item generic was edited`, async() => {
const result = await page
.waitToGetProperty(selectors.itemBasicData.generic, 'value');
expect(result).toEqual('16 - Pallet');
});
it(`should confirm the item long name was edited`, async() => {
const result = await page
.waitToGetProperty(selectors.itemBasicData.longName, 'value');
expect(result).toEqual('RS Rose of Purity');
});
it('should confirm isFragile checkbox is unchecked', async() => {
const result = await page
.checkboxState(selectors.itemBasicData.isFragile);
expect(result).toBe('checked');
});
it('should confirm isActive checkbox is unchecked', async() => {
const result = await page
.checkboxState(selectors.itemBasicData.isActiveCheckbox);
expect(result).toBe('unchecked');
});
it('should confirm the priceInKg checkbox is checked', async() => {
const result = await page
.checkboxState(selectors.itemBasicData.priceInKgCheckbox);
expect(result).toBe('checked');
});
it(`should confirm the item packingOut was edited`, async() => {
const result = await page
.waitToGetProperty(selectors.itemBasicData.packingOut, 'value');
expect(result).toEqual('5');
}); });
}); });

View File

@ -53,12 +53,4 @@ describe('Item edit tax path', () => {
expect(firstVatType).toEqual('Reduced VAT'); expect(firstVatType).toEqual('Reduced VAT');
}); });
// # #2680 Undo changes button bugs
xit(`should now click the undo changes button and see the form is restored`, async() => {
await page.waitToClick(selectors.itemTax.undoChangesButton);
const firstVatType = await page.waitToGetProperty(selectors.itemTax.firstClass, 'value');
expect(firstVatType).toEqual('General VAT');
});
}); });

View File

@ -1,6 +1,10 @@
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
form: 'vn-item-create form'
};
describe('Item Create', () => { describe('Item Create', () => {
let browser; let browser;
let page; let page;
@ -14,13 +18,6 @@ describe('Item Create', () => {
await browser.close(); await browser.close();
}); });
it(`should search for the item Infinity Gauntlet to confirm it isn't created yet`, async() => {
await page.doSearch('Infinity Gauntlet');
const resultsCount = await page.countElement(selectors.itemsIndex.searchResult);
expect(resultsCount).toEqual(0);
});
it('should access to the create item view by clicking the create floating button', async() => { it('should access to the create item view by clicking the create floating button', async() => {
await page.waitToClick(selectors.itemsIndex.createItemButton); await page.waitToClick(selectors.itemsIndex.createItemButton);
await page.waitForState('item.create'); await page.waitForState('item.create');
@ -37,44 +34,32 @@ describe('Item Create', () => {
}); });
it('should throw an error when insert an invalid priority', async() => { it('should throw an error when insert an invalid priority', async() => {
await page.write(selectors.itemCreateView.temporalName, 'Infinity Gauntlet'); const values = {
await page.autocompleteSearch(selectors.itemCreateView.type, 'Crisantemo'); name: 'Infinity Gauntlet',
await page.autocompleteSearch(selectors.itemCreateView.intrastat, 'Coral y materiales similares'); type: 'Crisantemo',
await page.autocompleteSearch(selectors.itemCreateView.origin, 'Holand'); intrastat: 'Coral y materiales similares',
await page.clearInput(selectors.itemCreateView.priority); origin: 'Holand',
await page.waitToClick(selectors.itemCreateView.createButton); priority: null
const message = await page.waitForSnackbar(); };
const message = await page.sendForm($.form, values);
expect(message.text).toContain('Valid priorities'); expect(message.text).toContain('Valid priorities');
}); });
it('should create the Infinity Gauntlet item', async() => { it('should create the Infinity Gauntlet item', async() => {
await page.autocompleteSearch(selectors.itemCreateView.priority, '2'); const values = {
await page.waitToClick(selectors.itemCreateView.createButton); name: 'Infinity Gauntlet',
const message = await page.waitForSnackbar(); type: 'Crisantemo',
intrastat: 'Coral y materiales similares',
origin: 'Holand',
priority: '2'
};
expect(message.text).toContain('Data saved!'); await page.fillForm($.form, values);
}); const formValues = await page.fetchForm($.form, Object.keys(values));
const message = await page.sendForm($.form);
it('should confirm Infinity Gauntlet item was created', async() => { expect(message.isSuccess).toBeTrue();
let result = await page expect(formValues).toEqual(values);
.waitToGetProperty(selectors.itemBasicData.name, 'value');
expect(result).toEqual('Infinity Gauntlet');
result = await page
.waitToGetProperty(selectors.itemBasicData.type, 'value');
expect(result).toEqual('Crisantemo');
result = await page
.waitToGetProperty(selectors.itemBasicData.intrastat, 'value');
expect(result).toEqual('5080000 Coral y materiales similares');
result = await page
.waitToGetProperty(selectors.itemBasicData.origin, 'value');
expect(result).toEqual('Holand');
}); });
}); });

View File

@ -1,6 +1,8 @@
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = selectors.itemFixedPrice;
describe('Item fixed prices path', () => { describe('Item fixed prices path', () => {
let browser; let browser;
let page; let page;
@ -22,63 +24,63 @@ describe('Item fixed prices path', () => {
}); });
it('should filter using all the fields', async() => { it('should filter using all the fields', async() => {
await page.write(selectors.itemFixedPrice.generalSearchFilter, 'item'); await page.write($.generalSearchFilter, 'item');
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
expect(httpRequest).toContain('search=item'); expect(httpRequest).toContain('search=item');
await page.click(selectors.itemFixedPrice.chip); await page.click($.chip);
await page.click(selectors.itemFixedPrice.reignFilter); await page.click($.reignFilter);
expect(httpRequest).toContain('categoryFk'); expect(httpRequest).toContain('categoryFk');
await page.autocompleteSearch(selectors.itemFixedPrice.typeFilter, 'Alstroemeria'); await page.autocompleteSearch($.typeFilter, 'Alstroemeria');
expect(httpRequest).toContain('typeFk'); expect(httpRequest).toContain('typeFk');
await page.click(selectors.itemFixedPrice.chip); await page.click($.chip);
await page.autocompleteSearch(selectors.itemFixedPrice.buyerFilter, 'buyerNick'); await page.autocompleteSearch($.buyerFilter, 'buyerNick');
expect(httpRequest).toContain('buyerFk'); expect(httpRequest).toContain('buyerFk');
await page.click(selectors.itemFixedPrice.chip); await page.click($.chip);
await page.autocompleteSearch(selectors.itemFixedPrice.warehouseFilter, 'Algemesi'); await page.autocompleteSearch($.warehouseFilter, 'Algemesi');
expect(httpRequest).toContain('warehouseFk'); expect(httpRequest).toContain('warehouseFk');
await page.click(selectors.itemFixedPrice.chip); await page.click($.chip);
await page.click(selectors.itemFixedPrice.mineFilter); await page.click($.mineFilter);
expect(httpRequest).toContain('mine=true'); expect(httpRequest).toContain('mine=true');
await page.click(selectors.itemFixedPrice.chip); await page.click($.chip);
await page.click(selectors.itemFixedPrice.hasMinPriceFilter); await page.click($.hasMinPriceFilter);
expect(httpRequest).toContain('hasMinPrice=true'); expect(httpRequest).toContain('hasMinPrice=true');
await page.click(selectors.itemFixedPrice.chip); await page.click($.chip);
await page.click(selectors.itemFixedPrice.addTag); await page.click($.addTag);
await page.autocompleteSearch(selectors.itemFixedPrice.tagFilter, 'Color'); await page.autocompleteSearch($.tagFilter, 'Color');
await page.autocompleteSearch(selectors.itemFixedPrice.tagValueFilter, 'Brown'); await page.autocompleteSearch($.tagValueFilter, 'Brown');
expect(httpRequest).toContain('tags'); expect(httpRequest).toContain('tags');
await page.click(selectors.itemFixedPrice.chip); await page.click($.chip);
}); });
it('should click on the add new fixed price button', async() => { it('should click on the add new fixed price button', async() => {
await page.waitToClick(selectors.itemFixedPrice.add); await page.waitToClick($.add);
await page.waitForSelector(selectors.itemFixedPrice.fourthFixedPrice); await page.waitForSelector($.fourthFixedPrice);
}); });
it('should fill the fixed price data', async() => { it('should fill the fixed price data', async() => {
const now = Date.vnNew(); const now = Date.vnNew();
await page.autocompleteSearch(selectors.itemFixedPrice.fourthWarehouse, 'Warehouse one'); await page.autocompleteSearch($.fourthWarehouse, 'Warehouse one');
await page.writeOnEditableTD(selectors.itemFixedPrice.fourthGroupingPrice, '1'); await page.writeOnEditableTD($.fourthGroupingPrice, '1');
await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPackingPrice, '1'); await page.writeOnEditableTD($.fourthPackingPrice, '1');
await page.write(selectors.itemFixedPrice.fourthMinPrice, '1'); await page.write($.fourthMinPrice, '1');
await page.pickDate(selectors.itemFixedPrice.fourthStarted, now); await page.pickDate($.fourthStarted, now);
await page.pickDate(selectors.itemFixedPrice.fourthEnded, now); await page.pickDate($.fourthEnded, now);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');
@ -86,8 +88,9 @@ describe('Item fixed prices path', () => {
it('should reload the section and check the created price has the expected ID', async() => { it('should reload the section and check the created price has the expected ID', async() => {
await page.goto(`http://localhost:5000/#!/item/fixed-price`); await page.goto(`http://localhost:5000/#!/item/fixed-price`);
await page.autocompleteSearch($.warehouseFilter, 'Warehouse one');
const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value'); await page.click($.chip);
const result = await page.waitToGetProperty($.fourthItemID, 'value');
expect(result).toContain('13'); expect(result).toContain('13');
}); });

View File

@ -220,14 +220,25 @@ describe('Ticket Edit sale path', () => {
it('should log in as salesAssistant and navigate to ticket sales', async() => { it('should log in as salesAssistant and navigate to ticket sales', async() => {
await page.loginAndModule('salesAssistant', 'ticket'); await page.loginAndModule('salesAssistant', 'ticket');
await page.accessToSearchResult('16'); await page.accessToSearchResult('17');
await page.accessToSection('ticket.card.sale'); await page.accessToSection('ticket.card.sale');
}); });
it('should select the third sale and create a refund', async() => { it('should select the first sale and create a refund with warehouse', async() => {
await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); await page.waitToClick(selectors.ticketSales.firstSaleCheckbox);
await page.waitToClick(selectors.ticketSales.moreMenu); await page.waitToClick(selectors.ticketSales.moreMenu);
await page.waitToClick(selectors.ticketSales.moreMenuRefund); await page.waitToClick(selectors.ticketSales.moreMenuRefund);
await page.waitToClick(selectors.ticketSales.refundWithWarehouse);
await page.waitForSnackbar();
await page.waitForState('ticket.card.sale');
});
it('should select the first sale and create a refund without warehouse', async() => {
await page.accessToSearchResult('18');
await page.waitToClick(selectors.ticketSales.firstSaleCheckbox);
await page.waitToClick(selectors.ticketSales.moreMenu);
await page.waitToClick(selectors.ticketSales.moreMenuRefund);
await page.waitToClick(selectors.ticketSales.refundWithoutWarehouse);
await page.waitForSnackbar(); await page.waitForSnackbar();
await page.waitForState('ticket.card.sale'); await page.waitForState('ticket.card.sale');
}); });
@ -246,7 +257,6 @@ describe('Ticket Edit sale path', () => {
it('should select the third sale and create a claim of it', async() => { it('should select the third sale and create a claim of it', async() => {
await page.accessToSearchResult('16'); await page.accessToSearchResult('16');
await page.accessToSection('ticket.card.sale'); await page.accessToSection('ticket.card.sale');
await page.waitToClick(selectors.ticketSales.firstSaleCheckbox);
await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox); await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox);
await page.waitToClick(selectors.ticketSales.moreMenu); await page.waitToClick(selectors.ticketSales.moreMenu);
await page.waitToClick(selectors.ticketSales.moreMenuCreateClaim); await page.waitToClick(selectors.ticketSales.moreMenuCreateClaim);
@ -425,20 +435,6 @@ describe('Ticket Edit sale path', () => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
}); });
// tickets no longer update their totals instantly, a task performed ever 5-10 mins does it. disabled this test until it changes.
xit('should update all sales discount', async() => {
await page.closePopup();
await page.waitToClick(selectors.ticketSales.moreMenu);
await page.waitToClick(selectors.ticketSales.moreMenuUpdateDiscount);
await page.waitForSelector(selectors.ticketSales.moreMenuUpdateDiscountInput);
await page.type(selectors.ticketSales.moreMenuUpdateDiscountInput, '100');
await page.keyboard.press('Enter');
await page.waitForTextInElement(selectors.ticketSales.totalImport, '0.00');
const result = await page.waitToGetProperty(selectors.ticketSales.totalImport, 'innerText');
expect(result).toContain('0.00');
});
it('should log in as Production role and go to a target ticket summary', async() => { it('should log in as Production role and go to a target ticket summary', async() => {
await page.loginAndModule('production', 'ticket'); await page.loginAndModule('production', 'ticket');
await page.accessToSearchResult('13'); await page.accessToSearchResult('13');

View File

@ -1,6 +1,13 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
firstPackage: 'vn-autocomplete[label="Package"]',
firstQuantity: 'vn-ticket-package vn-horizontal:nth-child(1) vn-input-number[ng-model="package.quantity"]',
firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]',
addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]',
savePackagesButton: `button[type=submit]`
};
describe('Ticket Create packages path', () => { describe('Ticket Create packages path', () => {
let browser; let browser;
let page; let page;
@ -18,19 +25,19 @@ describe('Ticket Create packages path', () => {
}); });
it(`should attempt create a new package but receive an error if package is blank`, async() => { it(`should attempt create a new package but receive an error if package is blank`, async() => {
await page.waitToClick(selectors.ticketPackages.firstRemovePackageButton); await page.waitToClick($.firstRemovePackageButton);
await page.waitToClick(selectors.ticketPackages.addPackageButton); await page.waitToClick($.addPackageButton);
await page.write(selectors.ticketPackages.firstQuantity, '99'); await page.write($.firstQuantity, '99');
await page.waitToClick(selectors.ticketPackages.savePackagesButton); await page.waitToClick($.savePackagesButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Package cannot be blank'); expect(message.text).toContain('Package cannot be blank');
}); });
it(`should delete the first package and receive and error to save a new one with blank quantity`, async() => { it(`should delete the first package and receive and error to save a new one with blank quantity`, async() => {
await page.clearInput(selectors.ticketPackages.firstQuantity); await page.clearInput($.firstQuantity);
await page.autocompleteSearch(selectors.ticketPackages.firstPackage, 'Container medical box 1m'); await page.autocompleteSearch($.firstPackage, 'Container medical box 1m');
await page.waitToClick(selectors.ticketPackages.savePackagesButton); await page.waitToClick($.savePackagesButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Some fields are invalid'); expect(message.text).toContain('Some fields are invalid');
@ -40,15 +47,15 @@ describe('Ticket Create packages path', () => {
const result = await page const result = await page
.evaluate(selector => { .evaluate(selector => {
return document.querySelector(`${selector} input`).checkValidity(); return document.querySelector(`${selector} input`).checkValidity();
}, selectors.ticketPackages.firstQuantity); }, $.firstQuantity);
expect(result).toBeTruthy(); expect(result).toBeTruthy();
}); });
it(`should create a new package with correct data`, async() => { it(`should create a new package with correct data`, async() => {
await page.clearInput(selectors.ticketPackages.firstQuantity); await page.clearInput($.firstQuantity);
await page.write(selectors.ticketPackages.firstQuantity, '-99'); await page.write($.firstQuantity, '-99');
await page.waitToClick(selectors.ticketPackages.savePackagesButton); await page.waitToClick($.savePackagesButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');
@ -56,15 +63,15 @@ describe('Ticket Create packages path', () => {
it(`should confirm the first select is the expected one`, async() => { it(`should confirm the first select is the expected one`, async() => {
await page.reloadSection('ticket.card.package'); await page.reloadSection('ticket.card.package');
await page.waitForTextInField(selectors.ticketPackages.firstPackage, 'Container medical box 1m'); await page.waitForTextInField($.firstPackage, 'Container medical box 1m');
const result = await page.waitToGetProperty(selectors.ticketPackages.firstPackage, 'value'); const result = await page.waitToGetProperty($.firstPackage, 'value');
expect(result).toEqual('7 : Container medical box 1m'); expect(result).toEqual('Container medical box 1m');
}); });
it(`should confirm quantity is just a number and the string part was ignored by the imput number`, async() => { it(`should confirm quantity is just a number and the string part was ignored by the imput number`, async() => {
await page.waitForTextInField(selectors.ticketPackages.firstQuantity, '-99'); await page.waitForTextInField($.firstQuantity, '-99');
const result = await page.waitToGetProperty(selectors.ticketPackages.firstQuantity, 'value'); const result = await page.waitToGetProperty($.firstQuantity, 'value');
expect(result).toEqual('-99'); expect(result).toEqual('-99');
}); });

View File

@ -1,6 +1,11 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
form: 'vn-ticket-create-card',
moreMenu: 'vn-client-descriptor vn-icon-button[icon=more_vert]',
simpleTicketButton: '.vn-menu [name="simpleTicket"]'
};
describe('Ticket create from client path', () => { describe('Ticket create from client path', () => {
let browser; let browser;
let page; let page;
@ -16,20 +21,17 @@ describe('Ticket create from client path', () => {
await browser.close(); await browser.close();
}); });
it('should click the create simple ticket on the descriptor menu', async() => { it('should create simple ticket and check if the client details are the expected ones', async() => {
await page.waitToClick(selectors.clientDescriptor.moreMenu); await page.waitToClick($.moreMenu);
await page.waitToClick(selectors.clientDescriptor.simpleTicketButton); await page.waitToClick($.simpleTicketButton);
await page.waitForState('ticket.create'); await page.waitForState('ticket.create');
});
it('should check if the client details are the expected ones', async() => { const values = {
const client = await page client: 'Petter Parker',
.waitToGetProperty(selectors.createTicketView.client, 'value'); address: 'Petter Parker'
};
const formValues = await page.fetchForm($.form, Object.keys(values));
const address = await page expect(formValues).toEqual(values);
.waitToGetProperty(selectors.createTicketView.address, 'value');
expect(client).toContain('Petter Parker');
expect(address).toContain('20 Ingram Street');
}); });
}); });

View File

@ -1,5 +1,10 @@
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
newPayment: '.vn-dialog.shown',
anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr',
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable'
};
describe('Ticket index payout path', () => { describe('Ticket index payout path', () => {
let browser; let browser;
@ -8,17 +13,14 @@ describe('Ticket index payout path', () => {
beforeAll(async() => { beforeAll(async() => {
browser = await getBrowser(); browser = await getBrowser();
page = browser.page; page = browser.page;
await page.loginAndModule('administrative', 'ticket');
await page.waitForState('ticket.index');
}); });
afterAll(async() => { afterAll(async() => {
await browser.close(); await browser.close();
}); });
it('should navigate to the ticket index', async() => {
await page.loginAndModule('administrative', 'ticket');
await page.waitForState('ticket.index');
});
it('should check the second ticket from a client and 1 of another', async() => { it('should check the second ticket from a client and 1 of another', async() => {
await page.waitToClick(selectors.globalItems.searchButton); await page.waitToClick(selectors.globalItems.searchButton);
await page.waitToClick(selectors.ticketsIndex.thirdTicketCheckbox); await page.waitToClick(selectors.ticketsIndex.thirdTicketCheckbox);
@ -42,27 +44,27 @@ describe('Ticket index payout path', () => {
await page.waitForSelector(selectors.ticketsIndex.payoutCompany); await page.waitForSelector(selectors.ticketsIndex.payoutCompany);
}); });
it('should fill the company and bank to perform a payout', async() => { it('should fill the company and bank to perform a payout and check a new balance line was entered', async() => {
await page.autocompleteSearch(selectors.ticketsIndex.payoutCompany, 'VNL'); await page.fillForm($.newPayment, {
await page.autocompleteSearch(selectors.ticketsIndex.payoutBank, 'cash'); company: 'VNL',
await page.write(selectors.clientBalance.newPaymentAmount, '100'); bank: 'cash',
await page.write(selectors.ticketsIndex.payoutDescription, 'Payment'); amountPaid: 100,
await page.waitToClick(selectors.ticketsIndex.submitPayout); description: 'Payment',
viewReceipt: false
});
await page.respondToDialog('accept');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should navigate to the client balance section and check a new balance line was entered', async() => {
await page.waitToClick(selectors.globalItems.homeButton); await page.waitToClick(selectors.globalItems.homeButton);
await page.selectModule('client'); await page.selectModule('client');
await page.accessToSearchResult('1101'); await page.accessToSearchResult('1101');
await page.accessToSection('client.card.balance.index'); await page.accessToSection('client.card.balance.index');
await page.waitForSelector(selectors.clientBalance.anyBalanceLine); await page.waitForSelector($.anyBalanceLine);
const count = await page.countElement(selectors.clientBalance.anyBalanceLine); const count = await page.countElement($.anyBalanceLine);
const reference = await page.waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText'); const reference = await page.innerText($.firstLineReference);
expect(message.isSuccess).toBeTrue();
expect(count).toEqual(4); expect(count).toEqual(4);
expect(reference).toContain('Cash, Albaran: 7, 8Payment'); expect(reference).toContain('Payment');
}); });
}); });

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