4975-mdbVersion-last-method #1245

Merged
guillermo merged 12 commits from 4975-mdbVersion-last-method into dev 2023-01-16 11:40:23 +00:00
231 changed files with 4704 additions and 1854 deletions
Showing only changes of commit 868c2aaaef - Show all commits

21
CHANGELOG.md Normal file
View File

@ -0,0 +1,21 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2302.01] - 2023-01-12
### Added
- [General](Inicio) Permite recuperar la contraseña
- [Artículo](Datos Básicos) Añadido campo Unidades/Caja
### Changed
- [Tickets](Líneas preparadas) Actualizada sección para que sea más visual
### Fixed
- [General] Al utilizar el traductor de Google se descuadraban los iconos
### Removed
- [Tickets](Control clientes) Eliminada sección

View File

@ -29,8 +29,12 @@ module.exports = Self => {
filter = mergeFilters(filter, {where}); filter = mergeFilters(filter, {where});
const stmt = new ParameterizedSQL( const stmt = new ParameterizedSQL(
`SELECT * FROM campaign`); `SELECT * FROM (`);
stmt.merge('SELECT * FROM campaign');
stmt.merge(conn.makeWhere(filter.where)); stmt.merge(conn.makeWhere(filter.where));
stmt.merge('ORDER BY dated ASC');
stmt.merge('LIMIT 10000000000000000000');
stmt.merge(') sub');
stmt.merge('GROUP BY code'); stmt.merge('GROUP BY code');
stmt.merge(conn.makePagination(filter)); stmt.merge(conn.makePagination(filter));

View File

@ -43,6 +43,9 @@ module.exports = Self => {
if (!recipient) if (!recipient)
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`); throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);
if (process.env.NODE_ENV == 'test')
message = `[Test:Environment to user ${userId}] ` + message;
await models.Chat.create({ await models.Chat.create({
senderFk: sender.id, senderFk: sender.id,
recipient: `@${recipient.name}`, recipient: `@${recipient.name}`,

View File

@ -26,11 +26,30 @@ module.exports = Self => {
Self.setSaleQuantity = async(saleId, quantity) => { Self.setSaleQuantity = async(saleId, quantity) => {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {};
let tx;
const sale = await models.Sale.findById(saleId); if (typeof options == 'object')
return await sale.updateAttributes({ Object.assign(myOptions, options);
originalQuantity: sale.quantity,
quantity: quantity if (!myOptions.transaction) {
}); tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const sale = await models.Sale.findById(saleId, null, myOptions);
const saleUpdated = await sale.updateAttributes({
originalQuantity: sale.quantity,
quantity: quantity
}, myOptions);
if (tx) await tx.commit();
return saleUpdated;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
}; };
}; };

View File

@ -2,15 +2,26 @@ const models = require('vn-loopback/server/server').models;
describe('setSaleQuantity()', () => { describe('setSaleQuantity()', () => {
it('should change quantity sale', async() => { it('should change quantity sale', async() => {
const saleId = 30; const tx = await models.Ticket.beginTransaction({});
const newQuantity = 10;
const originalSale = await models.Sale.findById(saleId); try {
const options = {transaction: tx};
await models.Collection.setSaleQuantity(saleId, newQuantity); const saleId = 30;
const updateSale = await models.Sale.findById(saleId); const newQuantity = 10;
expect(updateSale.originalQuantity).toEqual(originalSale.quantity); const originalSale = await models.Sale.findById(saleId, null, options);
expect(updateSale.quantity).toEqual(newQuantity);
await models.Collection.setSaleQuantity(saleId, newQuantity, options);
const updateSale = await models.Sale.findById(saleId, null, options);
expect(updateSale.originalQuantity).toEqual(originalSale.quantity);
expect(updateSale.quantity).toEqual(newQuantity);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -0,0 +1,215 @@
const md5 = require('md5');
const fs = require('fs-extra');
module.exports = Self => {
Self.remoteMethodCtx('saveSign', {
description: 'Save sign',
accessType: 'WRITE',
accepts:
[
{
arg: 'signContent',
type: 'string',
required: true,
description: 'The sign content'
}, {
arg: 'tickets',
type: ['number'],
required: true,
description: 'The tickets'
}, {
arg: 'signedTime',
type: 'date',
description: 'The signed time'
}, {
arg: 'addressFk',
type: 'number',
required: true,
description: 'The address fk'
}
],
returns: {
type: 'Object',
root: true
},
http: {
path: `/saveSign`,
verb: 'POST'
}
});
async function createGestDoc(ticketId, userFk) {
const models = Self.app.models;
if (!await gestDocExists(ticketId)) {
const result = await models.Ticket.findOne({
where: {
id: ticketId
},
include: [
{
relation: 'warehouse',
scope: {
fields: ['id']
}
}, {
relation: 'client',
scope: {
fields: ['name']
}
}, {
relation: 'route',
scope: {
fields: ['id']
}
}
]
});
const warehouseFk = result.warehouseFk;
const companyFk = result.companyFk;
const client = result.client.name;
const route = result.route.id;
const resultDmsType = await models.DmsType.findOne({
where: {
code: 'Ticket'
}
});
const resultDms = await models.Dms.create({
dmsTypeFk: resultDmsType.id,
reference: ticketId,
description: `Ticket ${ticketId} Cliente ${client} Ruta ${route}`,
companyFk: companyFk,
warehouseFk: warehouseFk,
workerFk: userFk
});
return resultDms.insertId;
}
}
async function gestDocExists(ticket) {
const models = Self.app.models;
const result = await models.TicketDms.findOne({
where: {
ticketFk: ticket
},
fields: ['dmsFk']
});
if (result == null)
return false;
const isSigned = await models.Ticket.findOne({
where: {
id: ticket
},
fields: ['isSigned']
});
if (isSigned)
return true;
else
await models.Dms.destroyById(ticket);
}
async function dmsRecover(ticket, signContent) {
const models = Self.app.models;
await models.DmsRecover.create({
ticketFk: ticket,
sign: signContent
});
}
async function ticketGestdoc(ticket, dmsFk) {
const models = Self.app.models;
models.TicketDms.replaceOrCreate({
ticketFk: ticket,
dmsFk: dmsFk
});
const queryVnTicketSetState = `CALL vn.ticket_setState(?, ?)`;
await Self.rawSql(queryVnTicketSetState, [ticket, 'DELIVERED']);
}
async function updateGestdoc(file, ticket) {
const models = Self.app.models;
models.Dms.updateOne({
where: {
id: ticket
},
file: file,
contentType: 'image/png'
});
}
Self.saveSign = async(ctx, signContent, tickets, signedTime) => {
const models = Self.app.models;
let tx = await Self.beginTransaction({});
try {
const userId = ctx.req.accessToken.userId;
const dmsDir = `storage/dms`;
let image = null;
for (let i = 0; i < tickets.length; i++) {
const alertLevel = await models.TicketState.findOne({
where: {
ticketFk: tickets[i]
},
fields: ['alertLevel']
});
signedTime ? signedTime != undefined : signedTime = new Date();
if (alertLevel >= 2) {
let dir;
let id = null;
let fileName = null;
if (!await gestDocExists(tickets[i])) {
id = await createGestDoc(tickets[i], userId);
const hashDir = md5(id).substring(0, 3);
dir = `${dmsDir}/${hashDir}`;
if (!fs.existsSync(dir))
fs.mkdirSync(dir);
fileName = `${id}.png`;
image = `${dir}/${fileName}`;
} else
if (image != null) {
if (!fs.existsSync(dir))
dmsRecover(tickets[i], signContent);
else {
fs.writeFile(image, signContent, 'base64', async function(err) {
if (err) {
await tx.rollback();
return err.message;
}
});
}
} else
dmsRecover(tickets[i], signContent);
if (id != null && fileName.length > 0) {
ticketGestdoc(tickets[i], id);
updateGestdoc(id, fileName);
}
}
}
if (tx) await tx.commit();
return 'OK';
} catch (err) {
await tx.rollback();
throw err.message;
}
};
};

View File

@ -19,11 +19,11 @@ describe('getStarredModules()', () => {
}); });
it(`should return the starred modules for a given user`, async() => { it(`should return the starred modules for a given user`, async() => {
const newStarred = await app.models.StarredModule.create({workerFk: 9, moduleFk: 'Clients', position: 1}); const newStarred = await app.models.StarredModule.create({workerFk: 9, moduleFk: 'customer', position: 1});
const starredModules = await app.models.StarredModule.getStarredModules(ctx); const starredModules = await app.models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1); expect(starredModules.length).toEqual(1);
expect(starredModules[0].moduleFk).toEqual('Clients'); expect(starredModules[0].moduleFk).toEqual('customer');
// restores // restores
await app.models.StarredModule.destroyById(newStarred.id); await app.models.StarredModule.destroyById(newStarred.id);

View File

@ -26,29 +26,29 @@ describe('setPosition()', () => {
const filter = { const filter = {
where: { where: {
workerFk: ctx.req.accessToken.userId, workerFk: ctx.req.accessToken.userId,
moduleFk: 'Orders' moduleFk: 'order'
} }
}; };
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options); await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options); await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await app.models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(1); expect(orders.position).toEqual(1);
expect(clients.position).toEqual(2); expect(clients.position).toEqual(2);
await app.models.StarredModule.setPosition(ctx, 'Clients', 'left', options); await app.models.StarredModule.setPosition(ctx, 'customer', 'left', options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Orders'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await app.models.StarredModule.findOne(filter, options);
expect(clients.position).toEqual(1); expect(clients.position).toEqual(1);
@ -67,29 +67,29 @@ describe('setPosition()', () => {
const filter = { const filter = {
where: { where: {
workerFk: ctx.req.accessToken.userId, workerFk: ctx.req.accessToken.userId,
moduleFk: 'Orders' moduleFk: 'order'
} }
}; };
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options); await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options); await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await app.models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(1); expect(orders.position).toEqual(1);
expect(clients.position).toEqual(2); expect(clients.position).toEqual(2);
await app.models.StarredModule.setPosition(ctx, 'Orders', 'right', options); await app.models.StarredModule.setPosition(ctx, 'order', 'right', options);
filter.where.moduleFk = 'Orders'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await app.models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(2); expect(orders.position).toEqual(2);
@ -108,35 +108,35 @@ describe('setPosition()', () => {
const filter = { const filter = {
where: { where: {
workerFk: ctx.req.accessToken.userId, workerFk: ctx.req.accessToken.userId,
moduleFk: 'Items' moduleFk: 'item'
} }
}; };
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options); await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options); await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options); await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options); await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Items', options); await app.models.StarredModule.toggleStarredModule(ctx, 'item', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options); await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options); await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options); await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Zones', options); await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options);
const items = await app.models.StarredModule.findOne(filter, options); const items = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Claims'; filter.where.moduleFk = 'claim';
const claims = await app.models.StarredModule.findOne(filter, options); const claims = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Orders'; filter.where.moduleFk = 'order';
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Zones'; filter.where.moduleFk = 'zone';
const zones = await app.models.StarredModule.findOne(filter, options); const zones = await app.models.StarredModule.findOne(filter, options);
expect(items.position).toEqual(1); expect(items.position).toEqual(1);
@ -145,12 +145,12 @@ describe('setPosition()', () => {
expect(orders.position).toEqual(4); expect(orders.position).toEqual(4);
expect(zones.position).toEqual(5); expect(zones.position).toEqual(5);
await app.models.StarredModule.setPosition(ctx, 'Clients', 'right', options); await app.models.StarredModule.setPosition(ctx, 'customer', 'right', options);
filter.where.moduleFk = 'Orders'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await app.models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(3); expect(orders.position).toEqual(3);
@ -169,31 +169,31 @@ describe('setPosition()', () => {
const filter = { const filter = {
where: { where: {
workerFk: ctx.req.accessToken.userId, workerFk: ctx.req.accessToken.userId,
moduleFk: 'Items' moduleFk: 'item'
} }
}; };
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await app.models.StarredModule.toggleStarredModule(ctx, 'Items', options); await app.models.StarredModule.toggleStarredModule(ctx, 'item', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options); await app.models.StarredModule.toggleStarredModule(ctx, 'customer', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options); await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options); await app.models.StarredModule.toggleStarredModule(ctx, 'order', options);
await app.models.StarredModule.toggleStarredModule(ctx, 'Zones', options); await app.models.StarredModule.toggleStarredModule(ctx, 'zone', options);
const items = await app.models.StarredModule.findOne(filter, options); const items = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
let clients = await app.models.StarredModule.findOne(filter, options); let clients = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Claims'; filter.where.moduleFk = 'claim';
const claims = await app.models.StarredModule.findOne(filter, options); const claims = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Orders'; filter.where.moduleFk = 'order';
let orders = await app.models.StarredModule.findOne(filter, options); let orders = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Zones'; filter.where.moduleFk = 'zone';
const zones = await app.models.StarredModule.findOne(filter, options); const zones = await app.models.StarredModule.findOne(filter, options);
expect(items.position).toEqual(1); expect(items.position).toEqual(1);
@ -202,13 +202,13 @@ describe('setPosition()', () => {
expect(orders.position).toEqual(4); expect(orders.position).toEqual(4);
expect(zones.position).toEqual(5); expect(zones.position).toEqual(5);
await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options); await app.models.StarredModule.toggleStarredModule(ctx, 'claim', options);
await app.models.StarredModule.setPosition(ctx, 'Clients', 'right', options); await app.models.StarredModule.setPosition(ctx, 'customer', 'right', options);
filter.where.moduleFk = 'Clients'; filter.where.moduleFk = 'customer';
clients = await app.models.StarredModule.findOne(filter, options); clients = await app.models.StarredModule.findOne(filter, options);
filter.where.moduleFk = 'Orders'; filter.where.moduleFk = 'order';
orders = await app.models.StarredModule.findOne(filter, options); orders = await app.models.StarredModule.findOne(filter, options);
expect(orders.position).toEqual(2); expect(orders.position).toEqual(2);

View File

@ -21,15 +21,15 @@ describe('toggleStarredModule()', () => {
}); });
it('should create a new starred module and then remove it by calling the method again with same args', async() => { it('should create a new starred module and then remove it by calling the method again with same args', async() => {
const starredModule = await app.models.StarredModule.toggleStarredModule(ctx, 'Orders'); const starredModule = await app.models.StarredModule.toggleStarredModule(ctx, 'order');
let starredModules = await app.models.StarredModule.getStarredModules(ctx); let starredModules = await app.models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1); expect(starredModules.length).toEqual(1);
expect(starredModule.moduleFk).toEqual('Orders'); expect(starredModule.moduleFk).toEqual('order');
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId); expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
expect(starredModule.position).toEqual(starredModules.length); expect(starredModule.position).toEqual(starredModules.length);
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders'); await app.models.StarredModule.toggleStarredModule(ctx, 'order');
starredModules = await app.models.StarredModule.getStarredModules(ctx); starredModules = await app.models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(0); expect(starredModules.length).toEqual(0);

View File

@ -6,6 +6,7 @@ module.exports = Self => {
require('../methods/dms/removeFile')(Self); require('../methods/dms/removeFile')(Self);
require('../methods/dms/updateFile')(Self); require('../methods/dms/updateFile')(Self);
require('../methods/dms/deleteTrashFiles')(Self); require('../methods/dms/deleteTrashFiles')(Self);
require('../methods/dms/saveSign')(Self);
Self.checkRole = async function(ctx, id) { Self.checkRole = async function(ctx, id) {
const models = Self.app.models; const models = Self.app.models;

View File

@ -12,14 +12,9 @@ BEGIN
* @param vAuthorFk The notification author or %NULL if there is no author * @param vAuthorFk The notification author or %NULL if there is no author
* @return The notification id * @return The notification id
*/ */
DECLARE vNotificationFk INT;
SELECT id INTO vNotificationFk
FROM `notification`
WHERE `name` = vNotificationName;
INSERT INTO notificationQueue INSERT INTO notificationQueue
SET notificationFk = vNotificationFk, SET notificationFk = vNotificationName,
params = vParams, params = vParams,
authorFk = vAuthorFk; authorFk = vAuthorFk;

View File

View File

@ -0,0 +1,4 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('MdbApp', 'lock', 'WRITE', 'ALLOW', 'ROLE', 'developer'),
('MdbApp', 'unlock', 'WRITE', 'ALLOW', 'ROLE', 'developer');

View File

@ -0,0 +1 @@
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`) VALUES ('Dms','saveSign','*','ALLOW','employee');

View File

@ -0,0 +1,438 @@
DROP PROCEDURE IF EXISTS `sage`.`accountingMovements_add`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sage`.`accountingMovements_add`(vYear INT, vCompanyFk INT)
BEGIN
/**
* Traslada la info de contabilidad generada en base a vn.XDiario a la tabla sage.movConta para poder ejecutar posteriormente el proceso de importación de datos de SQL Server
* Solo traladará los asientos marcados con el campo vn.XDiario.enlazadoSage = FALSE
* @vYear Año contable del que se quiere trasladar la información
* @vCompanyFk Empresa de la que se quiere trasladar datos
*/
DECLARE vDatedFrom DATETIME;
DECLARE vDatedTo DATETIME;
DECLARE vDuaTransactionFk INT;
DECLARE vTaxImportFk INT;
DECLARE vTaxImportReducedFk INT;
DECLARE vTaxImportSuperReducedFk INT;
DECLARE vTransactionExportFk INT;
DECLARE vTransactionExportTaxFreeFk INT;
DECLARE vSerialDua VARCHAR(1) DEFAULT 'D';
DECLARE vInvoiceTypeInformativeCode VARCHAR(1);
DECLARE vCountryCanariasCode, vCountryCeutaMelillaCode VARCHAR(2) ;
DECLARE vBookEntries TEXT;
SELECT SiglaNacion INTO vCountryCanariasCode
FROM Naciones
WHERE Nacion ='ISLAS CANARIAS';
SELECT SiglaNacion INTO vCountryCeutaMelillaCode
FROM Naciones
WHERE Nacion ='CEUTA Y MELILLA';
SELECT CodigoTransaccion INTO vDuaTransactionFk
FROM TiposTransacciones
WHERE Transaccion = 'Import. bienes y serv. corrientes pdte. liquidar';
SELECT CodigoIva INTO vTaxImportFk
FROM TiposIva
WHERE Iva = 'IVA 21% importaciones';
SELECT CodigoIva INTO vTaxImportReducedFk
FROM TiposIva
WHERE Iva = 'IVA 10% importaciones';
SELECT CodigoIva INTO vTaxImportSuperReducedFk
FROM TiposIva
WHERE Iva = 'H.P. IVA Soportado Impor 4%';
SELECT CodigoTransaccion INTO vTransactionExportFk
FROM TiposTransacciones
WHERE Transaccion = 'Exportaciones definitivas';
SELECT CodigoTransaccion INTO vTransactionExportTaxFreeFk
FROM TiposTransacciones
WHERE Transaccion = 'Envíos definitivos a Canarias, Ceuta y Melilla';
SELECT codeSage INTO vInvoiceTypeInformativeCode
FROM invoiceType WHERE code ='informative';
SELECT CAST(CONCAT(vYear, '-01-01') AS DATETIME), util.dayEnd(CAST(CONCAT(vYear, '-12-31') AS DATE))
INTO vDatedFrom, vDatedTo;
TRUNCATE movContaIVA;
DELETE FROM movConta
WHERE enlazadoSage = FALSE
AND Asiento <> 1 ;
CALL clientSupplier_add(vCompanyFk);
CALL pgc_add(vCompanyFk);
CALL invoiceOut_manager(vYear, vCompanyFk);
CALL invoiceIn_manager(vYear, vCompanyFk);
INSERT INTO movConta(TipoEntrada,
Ejercicio,
CodigoEmpresa,
Asiento,
CargoAbono,
CodigoCuenta,
Contrapartida,
FechaAsiento,
Comentario,
ImporteAsiento,
NumeroPeriodo,
FechaGrabacion,
CodigoDivisa,
ImporteCambio,
ImporteDivisa,
FactorCambio,
IdProcesoIME,
TipoCarteraIME,
TipoAnaliticaIME,
StatusTraspasadoIME,
TipoImportacionIME,
Metalico347,
BaseIva1,
PorBaseCorrectora1,
PorIva1,
CuotaIva1,
PorRecargoEquivalencia1,
RecargoEquivalencia1,
CodigoTransaccion1,
BaseIva2,
PorBaseCorrectora2,
PorIva2,
CuotaIva2,
PorRecargoEquivalencia2,
RecargoEquivalencia2,
CodigoTransaccion2,
BaseIva3,
PorBaseCorrectora3,
PorIva3,
CuotaIva3,
PorRecargoEquivalencia3,
RecargoEquivalencia3,
CodigoTransaccion3,
BaseIva4,
PorBaseCorrectora4,
PorIva4,
CuotaIva4,
PorRecargoEquivalencia4,
RecargoEquivalencia4,
CodigoTransaccion4,
Año,
Serie,
Factura,
SuFacturaNo,
FechaFactura,
ImporteFactura,
TipoFactura,
CodigoCuentaFactura,
CifDni,
Nombre,
CodigoRetencion,
BaseRetencion,
PorRetencion,
ImporteRetencion,
SiglaNacion,
EjercicioFactura,
FechaOperacion,
Exclusion347,
MantenerAsiento,
ClaveOperacionFactura_,
TipoRectificativa,
FechaFacturaOriginal,
BaseImponibleOriginal,
CuotaIvaOriginal,
ClaseAbonoRectificativas,
RecargoEquivalenciaOriginal,
LibreA1,
CodigoIva1,
CodigoIva2,
CodigoIva3,
CodigoIva4,
IvaDeducible1,
IvaDeducible2,
IvaDeducible3,
IvaDeducible4,
Intracomunitaria
)
SELECT 'EN' TipoEntrada,
YEAR(x.FECHA) Ejercicio,
company_getCode(vCompanyFk) AS CodigoEmpresa,
x.ASIEN Asiento,
IF(EURODEBE <> 0 OR (EURODEBE = 0 AND EUROHABER IS NULL), 'D', 'H') CargoAbono,
x.SUBCTA CodigoCuenta,
x.CONTRA Contrapartida,
x.FECHA FechaAsiento,
x.CONCEPTO Comentario,
IF(x.EURODEBE, x.EURODEBE, x.EUROHABER) ImporteAsiento,
MONTH(x.FECHA) NumeroPeriodo,
IF(sub2.FECREGCON IS NULL, sub2.FECHA_EX, sub2.FECREGCON) FechaGrabacion,
IF(x.CAMBIO, IFNULL(mci.CodigoDivisa, sub3.code), '') CodigoDivisa,
x.CAMBIO ImporteCambio,
IFNULL(x.DEBEME, x.HABERME) ImporteDivisa,
IF(x.CAMBIO, TRUE, FALSE) FactorCambio,
NULL IdProcesoIME,
0 TipoCarteraIME,
0 TipoAnaliticaIME,
0 StatusTraspasadoIME,
0 TipoImportacionIME,
x.METAL Metalico347,
mci.BaseIva1,
mci.PorBaseCorrectora1,
mci.PorIva1,
mci.CuotaIva1,
mci.PorRecargoEquivalencia1,
mci.RecargoEquivalencia1,
mci.CodigoTransaccion1,
mci.BaseIva2,
mci.PorBaseCorrectora2,
mci.PorIva2,
mci.CuotaIva2,
mci.PorRecargoEquivalencia2,
mci.RecargoEquivalencia2,
mci.CodigoTransaccion2,
mci.BaseIva3,
mci.PorBaseCorrectora3,
mci.PorIva3,
mci.CuotaIva3,
mci.PorRecargoEquivalencia3,
mci.RecargoEquivalencia3,
mci.CodigoTransaccion3,
mci.BaseIva4,
mci.PorBaseCorrectora4,
mci.PorIva4,
mci.CuotaIva4,
mci.PorRecargoEquivalencia4,
mci.RecargoEquivalencia4,
mci.CodigoTransaccion4,
mci.Año,
mci.Serie,
mci.Factura,
mci.SuFacturaNo,
mci.FechaFactura,
mci.ImporteFactura,
mci.TipoFactura,
mci.CodigoCuentaFactura,
mci.CifDni,
mci.Nombre,
mci.CodigoRetencion,
mci.BaseRetencion,
mci.PorRetencion,
mci.ImporteRetencion,
mci.SiglaNacion,
mci.EjercicioFactura,
mci.FechaOperacion,
mci.Exclusion347,
TRUE,
mci.ClaveOperacionFactura,
mci.TipoRectificativa,
mci.FechaFacturaOriginal,
mci.BaseImponibleOriginal,
mci.CuotaIvaOriginal,
mci.ClaseAbonoRectificativas,
mci.RecargoEquivalenciaOriginal,
mci.LibreA1,
mci.CodigoIva1,
mci.CodigoIva2,
mci.CodigoIva3,
mci.CodigoIva4,
mci.IvaDeducible1,
mci.IvaDeducible2,
mci.IvaDeducible3,
mci.IvaDeducible4,
mci.Intracomunitaria
FROM vn.XDiario x
LEFT JOIN movContaIVA mci ON mci.id = x.id
LEFT JOIN (SELECT *
FROM (SELECT DISTINCT ASIEN, FECREGCON, FECHA_EX
FROM vn.XDiario
WHERE enlazadoSage = FALSE
ORDER BY ASIEN, FECREGCON DESC, FECHA_EX DESC
LIMIT 10000000000000000000
) sub GROUP BY ASIEN
)sub2 ON sub2.ASIEN = x.ASIEN
LEFT JOIN ( SELECT DISTINCT(account),cu.code
FROM vn.bank b
JOIN vn.currency cu ON cu.id = b.currencyFk
WHERE cu.code <> 'EUR' -- no se informa cuando la divisa en EUR
)sub3 ON sub3.account = x.SUBCTA
WHERE x.enlazadoSage = FALSE
AND x.empresa_id = vCompanyFk
AND x.FECHA BETWEEN vDatedFrom AND vDatedTo;
-- Metálicos
UPDATE movConta m
JOIN (SELECT Asiento,
c.socialName name,
c.fi,
n.SiglaNacion,
m.CodigoCuenta,
m.Contrapartida
FROM movConta m
LEFT JOIN vn.client c ON c.id = IF(m.CargoAbono = 'H',
CAST(SUBSTRING(m.CodigoCuenta, 3, LENGTH(m.CodigoCuenta)) AS UNSIGNED),
CAST(SUBSTRING(m.Contrapartida, 3, LENGTH(m.Contrapartida)) AS UNSIGNED))
LEFT JOIN Naciones n ON n.countryFk = c.countryFk
WHERE m.Metalico347 = TRUE
AND m.enlazadoSage = FALSE
)sub ON m.Asiento = sub.Asiento
SET m.Metalico347 = TRUE,
m.TipoFactura = vInvoiceTypeInformativeCode,
m.CifDni = sub.fi,
m.Nombre = sub.name,
m.SiglaNacion = sub.SiglaNacion
WHERE m.enlazadoSage = FALSE;
UPDATE movConta m
SET m.Metalico347 = FALSE,
m.TipoFactura = ''
WHERE m.CargoAbono = 'D'
AND m.enlazadoSage = FALSE;
-- Elimina cuentas de cliente/proveedor que no se utilizarán en la importación
DELETE cp
FROM clientesProveedores cp
LEFT JOIN movConta mc ON mc.codigoCuenta = cp.codigoCuenta
AND mc.enlazadoSage = FALSE
WHERE mc.codigoCuenta IS NULL;
-- Elimina cuentas contables que no se utilizarán en la importación
DELETE pc
FROM planCuentasPGC pc
LEFT JOIN movConta mc ON mc.codigoCuenta = pc.codigoCuenta
AND mc.enlazadoSage = FALSE
WHERE mc.codigoCuenta IS NULL;
-- DUAS
UPDATE movConta mci
JOIN vn.XDiario x ON x.ASIEN = mci.Asiento
JOIN TiposIva ti ON ti.CodigoIva = x.IVA
JOIN vn.pgcMaster pm ON pm.code = mci.CodigoCuenta COLLATE utf8mb3_unicode_ci
SET mci.BaseIva1 = x.BASEEURO,
mci.PorIva1 = x.IVA,
mci.CuotaIva1 = CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10, 2)),
mci.CodigoTransaccion1 = vDuaTransactionFk,
mci.CodigoIva1 = vTaxImportReducedFk,
mci.IvaDeducible1 = TRUE,
mci.FechaFacturaOriginal = x.FECHA_EX,
mci.SuFacturaNo = x.FACTURAEX,
mci.FechaOperacion = x.FECHA_OP,
mci.ImporteFactura = mci.ImporteFactura + x.BASEEURO + CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10, 2))
WHERE pm.description = 'HP Iva pendiente'
AND mci.enlazadoSage = FALSE
AND x.SERIE = vSerialDua COLLATE utf8mb3_unicode_ci
AND ti.Iva = 'I.V.A. 10% Nacional';
UPDATE movConta mci
JOIN vn.XDiario x ON x.ASIEN = mci.Asiento
JOIN TiposIva ti ON ti.CodigoIva = x.IVA
JOIN vn.pgcMaster pm ON pm.code = mci.CodigoCuenta COLLATE utf8mb3_unicode_ci
SET mci.BaseIva2 = x.BASEEURO ,
mci.PorIva2 = x.IVA,
mci.CuotaIva2 = CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10,2)),
mci.CodigoTransaccion2 = vDuaTransactionFk ,
mci.CodigoIva2 = vTaxImportFk,
mci.IvaDeducible2 = TRUE,
mci.ImporteFactura = mci.ImporteFactura + x.BASEEURO + CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10, 2))
WHERE pm.description = 'HP Iva pendiente'
AND mci.enlazadoSage = FALSE
AND x.SERIE = vSerialDua COLLATE utf8mb3_unicode_ci
AND ti.Iva = 'I.V.A. 21%';
UPDATE movConta mci
JOIN vn.XDiario x ON x.ASIEN = mci.Asiento
JOIN TiposIva ti ON ti.CodigoIva = x.IVA
JOIN vn.pgcMaster pm ON pm.code = mci.CodigoCuenta COLLATE utf8mb3_unicode_ci
SET mci.BaseIva3 = x.BASEEURO ,
mci.PorIva3 = x.IVA,
mci.CuotaIva3 = CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10,2)),
mci.CodigoTransaccion3 = vDuaTransactionFk ,
mci.CodigoIva3 = vTaxImportSuperReducedFk,
mci.IvaDeducible3 = TRUE,
mci.ImporteFactura = mci.ImporteFactura + x.BASEEURO + CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10, 2))
WHERE pm.description = 'HP Iva pendiente'
AND mci.enlazadoSage = FALSE
AND x.SERIE = vSerialDua COLLATE utf8mb3_unicode_ci
AND ti.Iva = 'I.V.A. 4%';
-- Rectificativas
UPDATE movConta mci
JOIN (SELECT x.ASIEN, x.FECHA_RT, x.SERIE_RT, x.FACTU_RT
FROM movConta mci
JOIN vn.XDiario x ON x.ASIEN = mci.Asiento
WHERE mci.TipoRectificativa > 0
AND mci.enlazadoSage = FALSE
AND x.FACTU_RT IS NOT NULL
GROUP BY x.ASIEN
) sub ON sub.ASIEN = mci.Asiento
SET mci.EjercicioFacturaOriginal = YEAR(sub.FECHA_RT),
mci.SerieFacturaOriginal = sub.SERIE_RT,
mci.NumeroFacturaOriginal = sub.FACTU_RT
WHERE mci.TipoRectificativa > 0 AND
mci.enlazadoSage = FALSE ;
-- Exportaciones Andorras y Canarias cambia TT (la cuenta es compartida)
UPDATE movConta mci
SET CodigoTransaccion1 = vTransactionExportTaxFreeFk,
CodigoTransaccion2 = IF(CodigoTransaccion2 = 0, 0, vTransactionExportTaxFreeFk),
CodigoTransaccion3 = IF(CodigoTransaccion3 = 0, 0, vTransactionExportTaxFreeFk),
CodigoTransaccion4 = IF(CodigoTransaccion4 = 0, 0, vTransactionExportTaxFreeFk)
WHERE enlazadoSage = FALSE
AND (CodigoTransaccion1 = vTransactionExportFk
OR CodigoTransaccion2 = vTransactionExportFk
OR CodigoTransaccion3 = vTransactionExportFk
OR CodigoTransaccion4 = vTransactionExportFk)
AND SiglaNacion IN (vCountryCanariasCode COLLATE utf8mb3_unicode_ci, vCountryCeutaMelillaCode COLLATE utf8mb3_unicode_ci);
UPDATE movConta mc
SET CodigoDivisa = 'USD',
FactorCambio = TRUE,
ImporteCambio = ABS( CAST( IF( ImporteDivisa <> 0 AND ImporteCambio = 0, ImporteAsiento / ImporteDivisa, ImporteCambio) AS DECIMAL( 10, 2)))
WHERE enlazadoSage = FALSE
AND (ImporteCambio <> 0 OR ImporteDivisa <> 0 OR FactorCambio);
UPDATE movConta mc
SET importeDivisa= -importeDivisa
WHERE enlazadoSage = FALSE
AND importeDivisa > 0
AND ImporteAsiento < 0;
-- Comprobación que los importes e ivas sean correctos, avisa vía CAU
SELECT GROUP_CONCAT(Asiento ORDER BY Asiento ASC SEPARATOR ',') INTO vBookEntries
FROM(SELECT sub.Asiento
FROM (SELECT mc.Asiento, SUM(mc.ImporteAsiento) amount
FROM movConta mc
WHERE mc.enlazadoSage = FALSE
GROUP BY mc.Asiento)sub
JOIN (SELECT x.ASIEN, SUM(IFNULL(x.EURODEBE,0) + IFNULL(x.EUROHABER,0)) amount
FROM vn.XDiario x
WHERE x.enlazadoSage = FALSE
GROUP BY ASIEN)sub2 ON sub2.ASIEN = sub.Asiento
WHERE sub.amount <> sub2.amount
UNION ALL
SELECT sub.Asiento
FROM (SELECT Asiento, SUM(BaseIva1 + BaseIva2 + BaseIva3 + BaseIva4) amountTaxableBase
FROM movConta
WHERE TipoFactura <> 'I'
AND enlazadoSage = FALSE
GROUP BY Asiento) sub
JOIN (SELECT ASIEN, SUM(BASEEURO) amountTaxableBase
FROM (SELECT ASIEN, SUM(BASEEURO) BASEEURO
FROM vn.XDiario
WHERE FACTURA
AND auxiliar <> '*'
AND enlazadoSage = FALSE
GROUP BY FACTURA, ASIEN)sub3
GROUP BY ASIEN) sub2 ON sub2.ASIEN = sub.Asiento
WHERE sub.amountTaxableBase<>sub2.amountTaxableBase
AND sub.amountTaxableBase/2 <> sub2.amountTaxableBase) sub;
IF vBookEntries IS NOT NULL THEN
SELECT util.notification_send ("book-entries-imported-incorrectly", CONCAT('{"bookEntries":"', vBookEntries,'"}'), null);
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,3 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('TicketLog', 'getChanges', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,12 @@
CREATE TABLE `vn`.`invoiceInConfig` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`retentionRate` int(3) NOT NULL,
`retentionName` varchar(25) NOT NULL,
`sageWithholdingFk` smallint(6) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `invoiceInConfig_sageWithholdingFk` FOREIGN KEY (`sageWithholdingFk`) REFERENCES `sage`.`TiposRetencion`(`CodigoRetencion`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`)
VALUES
(1, -2, 'Retención 2%', 2);

View File

@ -0,0 +1,11 @@
CREATE TABLE `vn`.`mdbApp` (
`app` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,
`baselineBranchFk` varchar(255) COLLATE utf8mb3_unicode_ci DEFAULT NULL,
`userFk` int(10) unsigned DEFAULT NULL,
`locked` datetime DEFAULT NULL,
PRIMARY KEY (`app`),
KEY `mdbApp_FK` (`userFk`),
KEY `mdbApp_FK_1` (`baselineBranchFk`),
CONSTRAINT `mdbApp_FK` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `mdbApp_FK_1` FOREIGN KEY (`baselineBranchFk`) REFERENCES `mdbBranch` (`name`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci

View File

@ -0,0 +1,24 @@
DROP FUNCTION IF EXISTS `util`.`notification_send`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`notification_send`(vNotificationName VARCHAR(255), vParams TEXT, vAuthorFk INT) RETURNS int(11)
MODIFIES SQL DATA
BEGIN
/**
* Sends a notification.
*
* @param vNotificationName The notification name
* @param vParams The notification parameters formatted as JSON
* @param vAuthorFk The notification author or %NULL if there is no author
* @return The notification id
*/
INSERT INTO notificationQueue
SET notificationFk = vNotificationName,
params = vParams,
authorFk = vAuthorFk;
RETURN LAST_INSERT_ID();
END$$
DELIMITER ;

View File

@ -0,0 +1,46 @@
DROP TRIGGER IF EXISTS `vn`.`supplier_beforeUpdate`;
USE `vn`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`supplier_beforeUpdate`
BEFORE UPDATE ON `supplier`
FOR EACH ROW
BEGIN
DECLARE vHasChange BOOL;
DECLARE vPayMethodChanged BOOL;
DECLARE vPayMethodHasVerified BOOL;
DECLARE vParams JSON;
DECLARE vOldPayMethodName VARCHAR(20);
DECLARE vNewPayMethodName VARCHAR(20);
SELECT hasVerified INTO vPayMethodHasVerified
FROM payMethod
WHERE id = NEW.payMethodFk;
SET vPayMethodChanged = NOT(NEW.payMethodFk <=> OLD.payMethodFk);
IF vPayMethodChanged THEN
SELECT name INTO vOldPayMethodName
FROM payMethod
WHERE id = OLD.payMethodFk;
SELECT name INTO vNewPayMethodName
FROM payMethod
WHERE id = NEW.payMethodFk;
SET vParams = JSON_OBJECT(
'name', NEW.name,
'oldPayMethod', vOldPayMethodName,
'newPayMethod', vNewPayMethodName
);
SELECT util.notification_send('supplier-pay-method-update', vParams, NULL) INTO @id;
END IF;
SET vHasChange = NOT(NEW.payDemFk <=> OLD.payDemFk AND NEW.payDay <=> OLD.payDay) OR vPayMethodChanged;
IF vHasChange AND vPayMethodHasVerified THEN
SET NEW.isPayMethodChecked = FALSE;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,8 @@
CREATE TABLE `vn`.`ticketSms` (
`smsFk` mediumint(8) unsigned NOT NULL,
`ticketFk` int(11) DEFAULT NULL,
PRIMARY KEY (`smsFk`),
KEY `ticketSms_FK_1` (`ticketFk`),
CONSTRAINT `ticketSms_FK` FOREIGN KEY (`smsFk`) REFERENCES `sms` (`id`) ON UPDATE CASCADE,
CONSTRAINT `ticketSms_FK_1` FOREIGN KEY (`ticketFk`) REFERENCES `ticket` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci

View File

@ -0,0 +1,104 @@
DROP PROCEDURE IF EXISTS `vn`.`ticket_canAdvance`;
DELIMITER $$
$$
CREATE 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 vn.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 vn.itemTicketOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM vn.itemEntryIn
WHERE landed >= vDateInventory
AND landed < vDateFuture
AND isVirtualStock = FALSE
AND warehouseInFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM vn.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 s.ticketFk futureId,
t2.ticketFk id,
sum((s.quantity <= IFNULL(st.amount,0))) hasStock,
count(DISTINCT s.id) saleCount,
t2.state,
t2.stateCode,
st.name futureState,
st.code futureStateCode,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
t2.ipt,
t.workerFk,
CAST(sum(litros) AS DECIMAL(10,0)) liters,
CAST(count(*) AS DECIMAL(10,0)) `lines`,
t2.shipped,
t.shipped futureShipped,
t2.totalWithVat,
t.totalWithVat futureTotalWithVat
FROM vn.ticket t
JOIN vn.ticketState ts ON ts.ticketFk = t.id
JOIN vn.state st ON st.id = ts.stateFk
JOIN vn.saleVolume sv ON t.id = sv.ticketFk
JOIN (SELECT
t2.id ticketFk,
t2.addressFk,
st.name state,
st.code stateCode,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt,
t2.shipped,
t2.totalWithVat
FROM vn.ticket t2
JOIN vn.sale s ON s.ticketFk = t2.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.ticketState ts ON ts.ticketFk = t2.id
JOIN vn.state st ON st.id = ts.stateFk
LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
WHERE t2.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance)
AND t2.warehouseFk = vWarehouseFk
GROUP BY t2.id) t2 ON t2.addressFk = t.addressFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN tmp.stock st ON st.itemFk = s.itemFk
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id;
DROP TEMPORARY TABLE tmp.stock;
END$$
DELIMITER ;
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('Ticket', 'getTicketsAdvance', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,73 @@
DROP PROCEDURE IF EXISTS `vn`.`ticket_canbePostponed`;
DELIMITER $$
$$
CREATE 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
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,2 @@
DROP PROCEDURE IF EXISTS `ticket_split`;
DROP PROCEDURE IF EXISTS `ticket_merge`;

View File

@ -0,0 +1,4 @@
INSERT INTO `util`.`notification` (id, name, description) VALUES(3, 'book-entries-imported-incorrectly', 'accounting entries exported incorrectly');
INSERT INTO `util`.`notificationAcl` (notificationFk, roleFk) VALUES(3, 5);
INSERT IGNORE INTO `util`.`notificationSubscription` (notificationFk, userFk) VALUES(3, 19663);

View File

@ -0,0 +1,7 @@
CREATE TABLE `vn`.`stateI18n` (
`stateFk` tinyint(3) unsigned NOT NULL,
`lang` char(2) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`stateFk`, `lang`),
CONSTRAINT `stateI18n_state_id` FOREIGN KEY (`stateFk`) REFERENCES `vn`.`state` (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;

View File

@ -0,0 +1,60 @@
UPDATE salix.module t
SET t.code = 'supplier'
WHERE t.code LIKE 'Suppliers' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'travel'
WHERE t.code LIKE 'Travels' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'ticket'
WHERE t.code LIKE 'Tickets' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'zone'
WHERE t.code LIKE 'Zones' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'monitor'
WHERE t.code LIKE 'Monitors' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'entry'
WHERE t.code LIKE 'Entries' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'invoiceIn'
WHERE t.code LIKE 'Invoices in' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'customer'
WHERE t.code LIKE 'Clients' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'route'
WHERE t.code LIKE 'Routes' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'item'
WHERE t.code LIKE 'Items' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'claim'
WHERE t.code LIKE 'Claims' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'user'
WHERE t.code LIKE 'Users' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'invoiceOut'
WHERE t.code LIKE 'Invoices out' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'order'
WHERE t.code LIKE 'Orders' ESCAPE '#';
UPDATE salix.module t
SET t.code = 'worker'
WHERE t.code LIKE 'Workers' ESCAPE '#';

View File

@ -0,0 +1,73 @@
INSERT INTO
`vn`.`stateI18n` (`stateFk`, `lang`, `name`)
VALUES
(1, 'en', 'Fix'),
(1, 'es', 'Arreglar'),
(2, 'en', 'Free'),
(2, 'es', 'Libre'),
(3, 'en', 'OK'),
(3, 'es', 'OK'),
(4, 'en', 'Printed'),
(4, 'es', 'Impreso'),
(5, 'en', 'Preparation'),
(5, 'es', 'Preparación'),
(6, 'en', 'In Review'),
(6, 'es', 'En Revisión'),
(7, 'en', 'Unfinished'),
(7, 'es', 'Sin Acabar'),
(8, 'en', 'Reviewed'),
(8, 'es', 'Revisado'),
(9, 'en', 'Fitting'),
(9, 'es', 'Encajando'),
(10, 'en', 'Fitted'),
(10, 'es', 'Encajado'),
(11, 'en', 'Billed'),
(11, 'es', 'Facturado'),
(12, 'en', 'Blocked'),
(12, 'es', 'Bloqueado'),
(13, 'en', 'In Delivery'),
(13, 'es', 'En Reparto'),
(14, 'en', 'Prepared'),
(14, 'es', 'Preparado'),
(15, 'en', 'Pending Collection'),
(15, 'es', 'Pendiente de Recogida'),
(16, 'en', 'Delivered'),
(16, 'es', 'Entregado'),
(20, 'en', 'Assigned'),
(20, 'es', 'Asignado'),
(21, 'en', 'Returned'),
(21, 'es', 'Retornado'),
(22, 'en', 'Pending to extend'),
(22, 'es', 'Pendiente ampliar'),
(23, 'en', 'URGENT'),
(23, 'es', 'URGENTE'),
(24, 'en', 'Chained'),
(24, 'es', 'Encadenado'),
(25, 'en', 'Shipping'),
(25, 'es', 'Embarcando'),
(26, 'en', 'Preparation'),
(26, 'es', 'Preparación previa'),
(27, 'en', 'Assisted preparation'),
(27, 'es', 'Preparación asistida'),
(28, 'en', 'Preparation OK'),
(28, 'es', 'Previa OK'),
(29, 'en', 'Preparation Printed'),
(29, 'es', 'Previa Impreso'),
(30, 'en', 'Shipped'),
(30, 'es', 'Embarcado'),
(31, 'en', 'Stowaway printed'),
(31, 'es', 'Polizón Impreso'),
(32, 'en', 'Stowaway OK'),
(32, 'es', 'Polizón OK'),
(33, 'en', 'Auto_Printed'),
(33, 'es', 'Auto_Impreso'),
(34, 'en', 'Pending payment'),
(34, 'es', 'Pendiente de pago'),
(35, 'en', 'Half-Embedded'),
(35, 'es', 'Semi-Encajado'),
(36, 'en', 'Preparation Reviewing'),
(36, 'es', 'Previa Revisando'),
(37, 'en', 'Preparation Reviewed'),
(37, 'es', 'Previa Revisado'),
(38, 'en', 'Preparation Chamber'),
(38, 'es', 'Preparación Cámara');

View File

@ -0,0 +1,16 @@
UPDATE `vn`.starredModule SET moduleFk = 'customer' WHERE moduleFk = 'Clients';
UPDATE `vn`.starredModule SET moduleFk = 'ticket' WHERE moduleFk = 'Tickets';
UPDATE `vn`.starredModule SET moduleFk = 'route' WHERE moduleFk = 'Routes';
UPDATE `vn`.starredModule SET moduleFk = 'zone' WHERE moduleFk = 'Zones';
UPDATE `vn`.starredModule SET moduleFk = 'order' WHERE moduleFk = 'Orders';
UPDATE `vn`.starredModule SET moduleFk = 'claim' WHERE moduleFk = 'Claims';
UPDATE `vn`.starredModule SET moduleFk = 'item' WHERE moduleFk = 'Items';
UPDATE `vn`.starredModule SET moduleFk = 'worker' WHERE moduleFk = 'Workers';
UPDATE `vn`.starredModule SET moduleFk = 'entry' WHERE moduleFk = 'Entries';
UPDATE `vn`.starredModule SET moduleFk = 'invoiceOut' WHERE moduleFk = 'Invoices out';
UPDATE `vn`.starredModule SET moduleFk = 'invoiceIn' WHERE moduleFk = 'Invoices in';
UPDATE `vn`.starredModule SET moduleFk = 'monitor' WHERE moduleFk = 'Monitors';
UPDATE `vn`.starredModule SET moduleFk = 'user' WHERE moduleFk = 'Users';
UPDATE `vn`.starredModule SET moduleFk = 'supplier' WHERE moduleFk = 'Suppliers';
UPDATE `vn`.starredModule SET moduleFk = 'travel' WHERE moduleFk = 'Travels';
UPDATE `vn`.starredModule SET moduleFk = 'shelving' WHERE moduleFk = 'Shelvings';

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`)
VALUES ('ItemShelvingSale','*','*','ALLOW','employee');

View File

@ -0,0 +1,4 @@
SET FOREIGN_KEY_CHECKS = 0;
ALTER TABLE `vn`.`report` MODIFY COLUMN id tinyint(3) unsigned NOT NULL AUTO_INCREMENT;
ALTER TABLE `vn`.`printer` MODIFY COLUMN id tinyint(3) unsigned NOT NULL AUTO_INCREMENT;
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -0,0 +1,2 @@
DELETE FROM `salix`.`ACL` WHERE model="SaleChecked";
DROP TABLE IF EXISTS `vn`.`saleChecked`;

View File

@ -690,7 +690,8 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
(27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()); (30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE());
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES VALUES
@ -922,21 +923,21 @@ INSERT INTO `vn`.`expeditionStateType`(`id`, `description`, `code`)
(3, 'Perdida', 'LOST'); (3, 'Perdida', 'LOST');
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`, `created`, `itemFk__`, `counter`, `workerFk`, `externalId`, `packagingFk`, `stateTypeFk`, `hostFk`) INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`, `created`, `counter`, `workerFk`, `externalId`, `packagingFk`, `stateTypeFk`, `hostFk`)
VALUES VALUES
(1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 15, 1, 18, 'UR9000006041', 94, 1, 'pc1'), (1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, 'UR9000006041', 94, 1, 'pc1'),
(2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 16, 2, 18, 'UR9000006041', 94, 1, NULL), (2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 18, 'UR9000006041', 94, 1, NULL),
(3, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 3, 18, 'UR9000006041', 94, 2, NULL), (3, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 18, 'UR9000006041', 94, 2, NULL),
(4, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 4, 18, 'UR9000006041', 94, 2, NULL), (4, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 4, 18, 'UR9000006041', 94, 2, NULL),
(5, 1, 2, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 1, 18, NULL, 94, 3, NULL), (5, 1, 2, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 3, NULL),
(6, 7, 3, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL, 1, 18, NULL, 94, 3, NULL), (6, 7, 3, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 1, 18, NULL, 94, 3, NULL),
(7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL, 1, 18, NULL, 94, NULL,NULL), (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), 1, 18, NULL, 94, NULL,NULL),
(8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL, 1, 18, NULL, 94, 1, NULL), (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), 1, 18, NULL, 94, 1, NULL),
(9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 1, 18, NULL, 94, 2, NULL), (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 2, NULL),
(10, 7, 7, 71, NOW(), NULL, 1, 18, NULL, 94, 3, NULL), (10, 7, 7, 71, NOW(), 1, 18, NULL, 94, 3, NULL),
(11, 7, 8, 71, NOW(), NULL, 1, 18, NULL, 94, 3, NULL), (11, 7, 8, 71, NOW(), 1, 18, NULL, 94, 3, NULL),
(12, 7, 9, 71, NOW(), NULL, 1, 18, NULL, 94, 3, NULL), (12, 7, 9, 71, NOW(), 1, 18, NULL, 94, 3, NULL),
(13, 1, 10,71, NOW(), NULL, 1, 18, NULL, 94, 3, NULL); (13, 1, 10,71, NOW(), 1, 18, NULL, 94, 3, NULL);
INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`) INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`)
@ -991,7 +992,8 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric
(33, 5, 14, 'Ranged weapon pistol 9mm', 50, 1.79, 0, 0, 0, util.VN_CURDATE()), (33, 5, 14, 'Ranged weapon pistol 9mm', 50, 1.79, 0, 0, 0, util.VN_CURDATE()),
(34, 4, 28, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (34, 4, 28, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
(35, 4, 29, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (35, 4, 29, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
(36, 4, 30, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()); (36, 4, 30, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
(37, 4, 31, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE());
INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`) INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`)
VALUES VALUES
@ -1141,10 +1143,10 @@ INSERT INTO `vn`.`itemShelving` (`itemFk`, `shelvingFk`, `visible`, `grouping`,
INSERT INTO `vn`.`itemShelvingSale` (`itemShelvingFk`, `saleFk`, `quantity`, `created`, `userFk`) INSERT INTO `vn`.`itemShelvingSale` (`itemShelvingFk`, `saleFk`, `quantity`, `created`, `userFk`)
VALUES VALUES
('1', '1', '1', '', '1106'), ('1', '1', '1', util.VN_CURDATE(), '1106'),
('2', '2', '5', '', '1106'), ('2', '2', '5', util.VN_CURDATE(), '1106'),
('1', '7', '1', '', '1106'), ('1', '7', '1', util.VN_CURDATE(), '1106'),
('2', '8', '5', '', '1106'); ('2', '8', '5', util.VN_CURDATE(), '1106');
INSERT INTO `vncontrol`.`accion`(`accion_id`, `accion`) INSERT INTO `vncontrol`.`accion`(`accion_id`, `accion`)
VALUES VALUES
@ -1333,9 +1335,9 @@ INSERT INTO `vn`.`itemTypeTag`(`id`, `itemTypeFk`, `tagFk`, `priority`)
CALL `vn`.`itemRefreshTags`(NULL); CALL `vn`.`itemRefreshTags`(NULL);
INSERT INTO `vn`.`itemLog` (`id`, `originFk`, `userFk`, `action`, `description`) INSERT INTO `vn`.`itemLog` (`id`, `originFk`, `userFk`, `action`, `description`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`, `changedModelValue`)
VALUES VALUES
('1', '1', '1', 'insert', 'We made a change!'); ('1', '1', '1', 'insert', 'We made a change!', 'Item', '{}', '{}', 1, '1');
INSERT INTO `vn`.`recovery`(`id`, `clientFk`, `started`, `finished`, `amount`, `period`) INSERT INTO `vn`.`recovery`(`id`, `clientFk`, `started`, `finished`, `amount`, `period`)
VALUES VALUES
@ -1777,7 +1779,7 @@ INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`)
INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`) INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`)
VALUES VALUES
(1, 1, 1, 21, 1, 1, 2, 5), (1, 1, 1, 21, 1, 1, 2, 5),
(2, 1, 1, 21, 7, 2, 2, 5), (2, 1, 2, 21, 7, 2, 2, 5),
(3, 2, 7, 21, 9, 3, 2, 5), (3, 2, 7, 21, 9, 3, 2, 5),
(4, 3, 7, 21, 15, 8, 2, 5), (4, 3, 7, 21, 15, 8, 2, 5),
(5, 4, 7, 21, 7, 8, 2, 5); (5, 4, 7, 21, 7, 8, 2, 5);
@ -2650,7 +2652,7 @@ INSERT INTO `vn`.`mdbVersion` (`app`, `branchFk`, `version`)
INSERT INTO `vn`.`accountingConfig` (`id`, `minDate`, `maxDate`) INSERT INTO `vn`.`accountingConfig` (`id`, `minDate`, `maxDate`)
VALUES VALUES
(1, '2022-01-01', '2023-01-01'); (1, CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR)), '-01-01'), CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL +1 YEAR)), '-01-01'));
INSERT INTO `vn`.`saleGroup` (`userFk`, `parkingFk`, `sectorFk`) INSERT INTO `vn`.`saleGroup` (`userFk`, `parkingFk`, `sectorFk`)
@ -2689,7 +2691,8 @@ INSERT INTO `util`.`notificationConfig`
INSERT INTO `util`.`notification` (`id`, `name`, `description`) INSERT INTO `util`.`notification` (`id`, `name`, `description`)
VALUES VALUES
(1, 'print-email', 'notification fixture one'); (1, 'print-email', 'notification fixture one'),
(4, 'supplier-pay-method-update', 'A supplier pay method has been updated');
INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`) INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
VALUES VALUES
@ -2704,7 +2707,8 @@ INSERT INTO `util`.`notificationQueue` (`id`, `notificationFk`, `params`, `autho
INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`) INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`)
VALUES VALUES
(1, 1109), (1, 1109),
(1, 1110); (1, 1110),
(3, 1109);
INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`) INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`)
VALUES VALUES
@ -2730,14 +2734,27 @@ UPDATE `account`.`user`
SET `hasGrant` = 1 SET `hasGrant` = 1
WHERE `id` = 66; WHERE `id` = 66;
INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldInstance, newInstance, changedModelId, `description`)
VALUES
(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', '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'");
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', 'open', 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', 'open', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all');
INSERT INTO `vn`.`mdbApp` (`app`, `baselineBranchFk`, `userFk`, `locked`)
VALUES
('foo', 'master', NULL, NULL),
('bar', 'test', 9, util.VN_NOW());
INSERT INTO `vn`.`ticketLog` (`id`, `originFk`, `userFk`, `action`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`) INSERT INTO `vn`.`ticketLog` (`id`, `originFk`, `userFk`, `action`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`)
VALUES VALUES
(1, 1, 9, 'insert', 'Ticket', '{}', '{"clientFk":1, "nickname": "Bat cave"}', 1); (1, 1, 9, 'insert', 'Ticket', '{}', '{"clientFk":1, "nickname": "Bat cave"}', 1);
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
VALUES VALUES
('lilium', 'dev', 'http://localhost:8080/#/'), ('lilium', 'dev', 'http://localhost:8080/#/'),
@ -2746,3 +2763,4 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) INSERT INTO `vn`.`payDemDetail` (`id`, `detail`)
VALUES VALUES
(1, 1); (1, 1);

View File

@ -16340,6 +16340,185 @@ CREATE TABLE `invoiceType` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `movConta`
--
DROP TABLE IF EXISTS `movConta`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `movConta` (
`OrdenMovimientos` int(11) NOT NULL AUTO_INCREMENT,
`MovPosicion` varchar(64) COLLATE utf8mb3_unicode_ci NOT NULL,
`Ejercicio` smallint(6) NOT NULL,
`CodigoEmpresa` smallint(6) NOT NULL,
`Asiento` int(11) NOT NULL,
`CargoAbono` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`CodigoCuenta` varchar(15) CHARACTER SET utf8mb3 NOT NULL,
`Contrapartida` varchar(15) COLLATE utf8mb3_unicode_ci NOT NULL,
`FechaAsiento` datetime NOT NULL,
`TipoDocumento` varchar(6) COLLATE utf8mb3_unicode_ci NOT NULL,
`DocumentoConta` varchar(9) COLLATE utf8mb3_unicode_ci NOT NULL,
`Comentario` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`ImporteAsiento` decimal(28,10) NOT NULL,
`CodigoDiario` smallint(6) NOT NULL,
`CodigoCanal` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`CodigoActividad` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`FechaVencimiento` datetime DEFAULT NULL,
`NumeroPeriodo` smallint(6) NOT NULL,
`CodigoUsuario` smallint(6) NOT NULL,
`FechaGrabacion` datetime NOT NULL,
`TipoEntrada` varchar(2) COLLATE utf8mb3_unicode_ci NOT NULL,
`CodigoDepartamento` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`CodigoSeccion` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`CodigoDivisa` varchar(3) COLLATE utf8mb3_unicode_ci NOT NULL,
`ImporteCambio` decimal(28,10) NOT NULL,
`ImporteDivisa` decimal(28,10) NOT NULL,
`FactorCambio` decimal(28,10) NOT NULL,
`CodigoProyecto` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`LibreN1` int(11) NOT NULL,
`LibreN2` int(11) NOT NULL,
`LibreA1` varchar(15) COLLATE utf8mb3_unicode_ci NOT NULL,
`LibreA2` varchar(15) COLLATE utf8mb3_unicode_ci NOT NULL,
`IdDelegacion` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`MovCartera` varchar(64) COLLATE utf8mb3_unicode_ci DEFAULT NULL,
`IdProcesoIME` varchar(64) COLLATE utf8mb3_unicode_ci NOT NULL,
`TipoCarteraIME` smallint(6) NOT NULL,
`TipoAnaliticaIME` smallint(6) NOT NULL,
`StatusTraspasadoIME` tinyint(4) NOT NULL,
`TipoImportacionIME` tinyint(4) NOT NULL,
`BaseIva1` decimal(28,10) NOT NULL,
`PorBaseCorrectora1` decimal(28,10) NOT NULL,
`PorIva1` decimal(28,10) NOT NULL,
`CuotaIva1` decimal(28,10) NOT NULL,
`PorRecargoEquivalencia1` decimal(28,10) NOT NULL,
`RecargoEquivalencia1` decimal(28,10) NOT NULL,
`CodigoTransaccion1` tinyint(4) NOT NULL,
`BaseIva2` decimal(28,10) NOT NULL,
`PorBaseCorrectora2` decimal(28,10) NOT NULL,
`PorIva2` decimal(28,10) NOT NULL,
`CuotaIva2` decimal(28,10) NOT NULL,
`PorRecargoEquivalencia2` decimal(28,10) NOT NULL,
`RecargoEquivalencia2` decimal(28,10) NOT NULL,
`CodigoTransaccion2` tinyint(4) NOT NULL,
`BaseIva3` decimal(28,10) NOT NULL,
`PorBaseCorrectora3` decimal(28,10) NOT NULL,
`PorIva3` decimal(28,10) NOT NULL,
`CuotaIva3` decimal(28,10) NOT NULL,
`PorRecargoEquivalencia3` decimal(28,10) NOT NULL,
`RecargoEquivalencia3` decimal(28,10) NOT NULL,
`CodigoTransaccion3` tinyint(4) NOT NULL,
`baseIva4` decimal(28,10) NOT NULL,
`PorBaseCorrectora4` decimal(28,10) NOT NULL,
`PorIva4` decimal(28,10) NOT NULL,
`CuotaIva4` decimal(28,10) NOT NULL,
`PorRecargoEquivalencia4` decimal(28,10) NOT NULL,
`RecargoEquivalencia4` decimal(28,10) NOT NULL,
`CodigoTransaccion4` tinyint(4) NOT NULL,
`Año` smallint(6) NOT NULL,
`Serie` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`Factura` int(11) NOT NULL,
`SuFacturaNo` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`FechaFactura` datetime NOT NULL,
`ImporteFactura` decimal(28,10) NOT NULL,
`TipoFactura` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`CodigoCuentaFactura` varchar(15) COLLATE utf8mb3_unicode_ci NOT NULL,
`CifDni` varchar(13) COLLATE utf8mb3_unicode_ci NOT NULL,
`Nombre` varchar(35) COLLATE utf8mb3_unicode_ci NOT NULL,
`CodigoRetencion` smallint(6) NOT NULL,
`BaseRetencion` decimal(28,10) NOT NULL,
`PorRetencion` decimal(28,10) NOT NULL,
`ImporteRetencion` decimal(28,10) NOT NULL,
`AbonoIva` smallint(6) NOT NULL,
`CodigoActividadF` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`Intracomunitaria` smallint(6) NOT NULL,
`CodigoTerritorio` smallint(6) NOT NULL,
`SiglaNacion` varchar(2) COLLATE utf8mb3_unicode_ci NOT NULL,
`RetencionInformativa` smallint(6) NOT NULL,
`EjercicioFacturaOriginal` smallint(6) NOT NULL,
`SerieFacturaOriginal` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`NumeroFacturaOriginal` int(11) NOT NULL,
`EjercicioFactura` smallint(6) NOT NULL,
`CobroPagoRetencion` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`FechaOperacion` datetime NOT NULL,
`Exclusion347` smallint(6) NOT NULL,
`MovIdentificadorIME` varchar(64) COLLATE utf8mb3_unicode_ci NOT NULL,
`Previsiones` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`MantenerAsiento` tinyint(4) NOT NULL,
`OrdenMovIME` smallint(6) NOT NULL,
`Metalico347` smallint(6) NOT NULL,
`ClaveOperacionFactura_` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`SerieAgrupacion_` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`NumeroFacturaInicial_` int(11) NOT NULL,
`NumeroFacturaFinal_` int(11) NOT NULL,
`IdAsientoExterno` text COLLATE utf8mb3_unicode_ci NOT NULL,
`IdDiarioExterno` varchar(10) COLLATE utf8mb3_unicode_ci NOT NULL,
`IdFacturaExterno` text COLLATE utf8mb3_unicode_ci NOT NULL,
`IdMovimiento` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`IdCuadre` smallint(6) NOT NULL,
`FechaCuadre` datetime NOT NULL,
`TipoCuadre` varchar(4) COLLATE utf8mb3_unicode_ci NOT NULL,
`AgrupacionCuadre` int(11) NOT NULL,
`StatusSaldo` smallint(6) NOT NULL,
`StatusConciliacion` smallint(6) NOT NULL,
`CodigoConciliacion` int(11) NOT NULL,
`FechaConciliacion` datetime NOT NULL,
`TipoConciliacion` smallint(6) NOT NULL,
`IndicadorContaBanco` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion3` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion4` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion5` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion6` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion7` varchar(40) COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion8` text COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion9` text COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion2` text COLLATE utf8mb3_unicode_ci NOT NULL,
`Descripcion1` text COLLATE utf8mb3_unicode_ci NOT NULL,
`Punteo1` smallint(6) NOT NULL,
`Punteo9` smallint(6) NOT NULL,
`Punteo8` smallint(6) NOT NULL,
`Punteo7` smallint(6) NOT NULL,
`Punteo6` smallint(6) NOT NULL,
`Punteo5` smallint(6) NOT NULL,
`Punteo4` smallint(6) NOT NULL,
`Punteo3` smallint(6) NOT NULL,
`Punteo2` smallint(6) NOT NULL,
`CodigoIva1` smallint(6) NOT NULL,
`CodigoIva2` smallint(6) NOT NULL,
`CodigoIva3` smallint(6) NOT NULL,
`CodigoIva4` smallint(6) NOT NULL,
`CriterioIva` tinyint(4) NOT NULL,
`FechaMaxVencimiento` datetime NOT NULL,
`TipoCriterioCaja` tinyint(4) NOT NULL,
`MovFacturaOrigenIME` text COLLATE utf8mb3_unicode_ci NOT NULL,
`IdFacturaExternoFinal` text COLLATE utf8mb3_unicode_ci NOT NULL,
`IdFacturaExternoInicial` text COLLATE utf8mb3_unicode_ci NOT NULL,
`IdFacturaExternoOriginal` text COLLATE utf8mb3_unicode_ci NOT NULL,
`NumFacturasExternoAgrupacion` int(11) NOT NULL,
`CodigoMedioCobro` varchar(1) COLLATE utf8mb3_unicode_ci NOT NULL,
`MedioCobro` varchar(31) COLLATE utf8mb3_unicode_ci NOT NULL,
`IvaDeducible1` smallint(6) NOT NULL DEFAULT 1,
`IvaDeducible2` smallint(6) NOT NULL DEFAULT 1,
`IvaDeducible3` smallint(6) NOT NULL DEFAULT 1,
`IvaDeducible4` smallint(6) NOT NULL DEFAULT 1,
`TipoRectificativa` smallint(6) NOT NULL,
`FechaFacturaOriginal` datetime NOT NULL,
`BaseImponibleOriginal` decimal(28,10) NOT NULL,
`CuotaIvaOriginal` decimal(28,10) NOT NULL,
`ClaseAbonoRectificativas` smallint(6) NOT NULL,
`RecargoEquivalenciaOriginal` decimal(28,10) NOT NULL,
`ObjetoFactura` text COLLATE utf8mb3_unicode_ci NOT NULL,
`enlazadoSage` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`OrdenMovimientos`,`LibreN1`),
KEY `ix_movconta2` (`IdProcesoIME`),
KEY `CodigoCuenta` (`CodigoCuenta`),
KEY `movConta_Asiento` (`Asiento`),
KEY `ix_movconta` (`enlazadoSage`,`IdProcesoIME`),
KEY `movConta_IdProcesoIME` (`IdProcesoIME`),
KEY `movConta_Asiento2` (`Asiento`,`IdProcesoIME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Table structure for table `movContaIVA` -- Table structure for table `movContaIVA`
-- --

View File

@ -84,7 +84,6 @@ IGNORETABLES=(
--ignore-table=vn.warehouseJoined --ignore-table=vn.warehouseJoined
--ignore-table=vn.workerTeam__ --ignore-table=vn.workerTeam__
--ignore-table=vn.XDiario__ --ignore-table=vn.XDiario__
--ignore-table=sage.movConta
--ignore-table=sage.movContaCopia --ignore-table=sage.movContaCopia
) )
mysqldump \ mysqldump \

View File

@ -30,7 +30,7 @@ export default {
firstModuleRemovePinIcon: 'vn-home a:nth-child(1) vn-icon[icon="remove_circle"]' firstModuleRemovePinIcon: 'vn-home a:nth-child(1) vn-icon[icon="remove_circle"]'
}, },
recoverPassword: { recoverPassword: {
recoverPasswordButton: 'vn-login a[ui-sref="recoverPassword"]', recoverPasswordButton: 'vn-login a[ui-sref="recover-password"]',
email: 'vn-recover-password vn-textfield[ng-model="$ctrl.email"]', email: 'vn-recover-password vn-textfield[ng-model="$ctrl.email"]',
sendEmailButton: 'vn-recover-password vn-submit', sendEmailButton: 'vn-recover-password vn-submit',
}, },
@ -311,10 +311,12 @@ export default {
firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr' firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr'
}, },
clientLog: { clientLog: {
lastModificationPreviousValue: 'vn-client-log vn-table vn-td.before', lastModificationPreviousValue: 'vn-client-log vn-tr table tr td.before',
lastModificationCurrentValue: 'vn-client-log vn-table vn-td.after', lastModificationCurrentValue: 'vn-client-log vn-tr table tr td.after',
penultimateModificationPreviousValue: 'vn-client-log vn-table vn-tr:nth-child(2) vn-td.before', namePreviousValue: 'vn-client-log vn-tr table tr:nth-child(1) td.before',
penultimateModificationCurrentValue: 'vn-client-log vn-table vn-tr:nth-child(2) vn-td.after' nameCurrentValue: 'vn-client-log vn-tr table tr:nth-child(1) td.after',
activePreviousValue: 'vn-client-log vn-tr:nth-child(2) table tr:nth-child(2) td.before',
activeCurrentValue: 'vn-client-log vn-tr:nth-child(2) table tr:nth-child(2) td.after'
}, },
clientBalance: { clientBalance: {
@ -461,6 +463,7 @@ export default {
generic: 'vn-autocomplete[ng-model="$ctrl.item.genericFk"]', generic: 'vn-autocomplete[ng-model="$ctrl.item.genericFk"]',
isFragile: 'vn-check[ng-model="$ctrl.item.isFragile"]', isFragile: 'vn-check[ng-model="$ctrl.item.isFragile"]',
longName: 'vn-textfield[ng-model="$ctrl.item.longName"]', longName: 'vn-textfield[ng-model="$ctrl.item.longName"]',
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', newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button',
@ -518,7 +521,7 @@ export default {
}, },
itemLog: { itemLog: {
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr', anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) > vn-td > vn-one:nth-child(3) > div span:nth-child(2)', fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(3) td.after',
}, },
ticketSummary: { ticketSummary: {
header: 'vn-ticket-summary > vn-card > h5', header: 'vn-ticket-summary > vn-card > h5',
@ -711,9 +714,10 @@ export default {
ticketLog: { ticketLog: {
firstTD: 'vn-ticket-log vn-table vn-td:nth-child(1)', firstTD: 'vn-ticket-log vn-table vn-td:nth-child(1)',
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]', logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
firstLogEntry: 'vn-ticket-log vn-data-viewer vn-tbody vn-tr', user: 'vn-ticket-log vn-tbody vn-tr vn-td:nth-child(2)',
changes: 'vn-ticket-log vn-data-viewer vn-tbody > vn-tr > vn-td:nth-child(7)', action: 'vn-ticket-log vn-tbody vn-tr vn-td:nth-child(4)',
id: 'vn-ticket-log vn-tr:nth-child(1) vn-one:nth-child(1) span' changes: 'vn-ticket-log vn-data-viewer vn-tbody vn-tr table tr:nth-child(2) td.after',
id: 'vn-ticket-log vn-tr:nth-child(1) table tr:nth-child(1) td.before'
}, },
ticketService: { ticketService: {
addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button', addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button',
@ -735,18 +739,16 @@ export default {
}, },
ticketFuture: { ticketFuture: {
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]', openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
originDated: 'vn-date-picker[label="Origin ETD"]', originDated: 'vn-date-picker[label="Origin date"]',
futureDated: 'vn-date-picker[label="Destination ETD"]', futureDated: 'vn-date-picker[label="Destination date"]',
shipped: 'vn-date-picker[label="Origin date"]',
tfShipped: 'vn-date-picker[label="Destination date"]',
linesMax: 'vn-textfield[label="Max Lines"]', linesMax: 'vn-textfield[label="Max Lines"]',
litersMax: 'vn-textfield[label="Max Liters"]', litersMax: 'vn-textfield[label="Max Liters"]',
ipt: 'vn-autocomplete[label="Origin IPT"]', ipt: 'vn-autocomplete[label="Origin IPT"]',
tfIpt: 'vn-autocomplete[label="Destination IPT"]', futureIpt: 'vn-autocomplete[label="Destination IPT"]',
tableIpt: 'vn-autocomplete[name="ipt"]', tableIpt: 'vn-autocomplete[name="ipt"]',
tableTfIpt: 'vn-autocomplete[name="tfIpt"]', tableFutureIpt: 'vn-autocomplete[name="futureIpt"]',
state: 'vn-autocomplete[label="Origin Grouped State"]', state: 'vn-autocomplete[label="Origin Grouped State"]',
tfState: 'vn-autocomplete[label="Destination Grouped State"]', futureState: 'vn-autocomplete[label="Destination Grouped State"]',
warehouseFk: 'vn-autocomplete[label="Warehouse"]', warehouseFk: 'vn-autocomplete[label="Warehouse"]',
problems: 'vn-check[label="With problems"]', problems: 'vn-check[label="With problems"]',
tableButtonSearch: 'vn-button[vn-tooltip="Search"]', tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
@ -755,9 +757,34 @@ export default {
firstCheck: 'tbody > tr:nth-child(1) > td > vn-check', firstCheck: 'tbody > tr:nth-child(1) > td > vn-check',
multiCheck: 'vn-multi-check', multiCheck: 'vn-multi-check',
tableId: 'vn-textfield[name="id"]', tableId: 'vn-textfield[name="id"]',
tableTfId: 'vn-textfield[name="ticketFuture"]', tableFutureId: 'vn-textfield[name="futureId"]',
tableLiters: 'vn-textfield[name="litersMax"]', tableLiters: 'vn-textfield[name="liters"]',
tableLines: 'vn-textfield[name="linesMax"]', tableLines: 'vn-textfield[name="lines"]',
submit: 'vn-submit[label="Search"]',
table: 'tbody > tr:not(.empty-rows)'
},
ticketAdvance: {
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
dateFuture: 'vn-date-picker[label="Origin date"]',
dateToAdvance: 'vn-date-picker[label="Destination date"]',
linesMax: 'vn-textfield[label="Max Lines"]',
litersMax: 'vn-textfield[label="Max Liters"]',
futureIpt: 'vn-autocomplete[label="Origin IPT"]',
ipt: 'vn-autocomplete[label="Destination IPT"]',
tableIpt: 'vn-autocomplete[name="ipt"]',
tableFutureIpt: 'vn-autocomplete[name="futureIpt"]',
futureState: 'vn-autocomplete[label="Origin Grouped State"]',
state: 'vn-autocomplete[label="Destination Grouped State"]',
warehouseFk: 'vn-autocomplete[label="Warehouse"]',
tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
moveButton: 'vn-button[vn-tooltip="Advance tickets"]',
acceptButton: '.vn-confirm.shown button[response="accept"]',
multiCheck: 'vn-multi-check',
tableId: 'vn-textfield[name="id"]',
tableFutureId: 'vn-textfield[name="futureId"]',
tableLiters: 'vn-textfield[name="liters"]',
tableLines: 'vn-textfield[name="lines"]',
tableStock: 'vn-textfield[name="hasStock"]',
submit: 'vn-submit[label="Search"]', submit: 'vn-submit[label="Search"]',
table: 'tbody > tr:not(.empty-rows)' table: 'tbody > tr:not(.empty-rows)'
}, },
@ -1100,7 +1127,7 @@ export default {
undoChanges: 'vn-travel-basic-data vn-button[label="Undo changes"]' undoChanges: 'vn-travel-basic-data vn-button[label="Undo changes"]'
}, },
travelLog: { travelLog: {
firstLogFirstTD: 'vn-travel-log vn-tbody > vn-tr > vn-td:nth-child(1) > div' firstLogFirstTD: 'vn-travel-log vn-tbody > vn-tr > vn-td:nth-child(5)'
}, },
travelThermograph: { travelThermograph: {
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]', add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors'; import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
describe('Login path', async() => { describe('RecoverPassword path', async() => {
let browser; let browser;
let page; let page;
@ -10,7 +10,7 @@ describe('Login path', async() => {
page = browser.page; page = browser.page;
await page.waitToClick(selectors.recoverPassword.recoverPasswordButton); await page.waitToClick(selectors.recoverPassword.recoverPasswordButton);
await page.waitForState('recoverPassword'); await page.waitForState('recover-password');
}); });
afterAll(async() => { afterAll(async() => {

View File

@ -67,22 +67,22 @@ describe('Client Edit web access path', () => {
}); });
it(`should confirm the last log shows the updated client name and no modifications on active checkbox`, async() => { it(`should confirm the last log shows the updated client name and no modifications on active checkbox`, async() => {
let lastModificationPreviousValue = await page let namePreviousValue = await page
.waitToGetProperty(selectors.clientLog.lastModificationPreviousValue, 'innerText'); .waitToGetProperty(selectors.clientLog.namePreviousValue, 'innerText');
let lastModificationCurrentValue = await page let nameCurrentValue = await page
.waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText'); .waitToGetProperty(selectors.clientLog.nameCurrentValue, 'innerText');
expect(lastModificationPreviousValue).toEqual('name MaxEisenhardt active false'); expect(namePreviousValue).toEqual('MaxEisenhardt');
expect(lastModificationCurrentValue).toEqual('name Legion active false'); expect(nameCurrentValue).toEqual('Legion');
}); });
it(`should confirm the penultimate log shows the updated active and no modifications on client name`, async() => { it(`should confirm the penultimate log shows the updated active and no modifications on client name`, async() => {
let penultimateModificationPreviousValue = await page let activePreviousValue = await page
.waitToGetProperty(selectors.clientLog.penultimateModificationPreviousValue, 'innerText'); .waitToGetProperty(selectors.clientLog.activePreviousValue, 'innerText');
let penultimateModificationCurrentValue = await page let activeCurrentValue = await page
.waitToGetProperty(selectors.clientLog.penultimateModificationCurrentValue, 'innerText'); .waitToGetProperty(selectors.clientLog.activeCurrentValue, 'innerText');
expect(penultimateModificationPreviousValue).toEqual('name MaxEisenhardt active true'); expect(activePreviousValue).toEqual('✓');
expect(penultimateModificationCurrentValue).toEqual('name MaxEisenhardt active false'); expect(activeCurrentValue).toEqual('✗');
}); });
}); });

View File

@ -43,7 +43,7 @@ describe('Client log path', () => {
let lastModificationCurrentValue = await page. let lastModificationCurrentValue = await page.
waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText'); waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText');
expect(lastModificationPreviousValue).toEqual('name DavidCharlesHaller'); expect(lastModificationPreviousValue).toEqual('DavidCharlesHaller');
expect(lastModificationCurrentValue).toEqual('name this is a test'); expect(lastModificationCurrentValue).toEqual('this is a test');
}); });
}); });

View File

@ -2,68 +2,32 @@ import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
describe('Worker summary path', () => { describe('Worker summary path', () => {
const workerId = 3;
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('employee', 'worker'); await page.loginAndModule('employee', 'worker');
const httpDataResponse = page.waitForResponse(response => {
return response.status() === 200 && response.url().includes(`Workers/${workerId}`);
});
await page.accessToSearchResult('agencyNick'); await page.accessToSearchResult('agencyNick');
await httpDataResponse;
}); });
afterAll(async() => { afterAll(async() => {
await browser.close(); await browser.close();
}); });
it('should reach the employee summary section', async() => { it('should reach the employee summary section and check all properties', async() => {
await page.waitForState('worker.card.summary'); expect(await page.getProperty(selectors.workerSummary.header, 'innerText')).toEqual('agency agency');
}); expect(await page.getProperty(selectors.workerSummary.id, 'innerText')).toEqual('3');
expect(await page.getProperty(selectors.workerSummary.email, 'innerText')).toEqual('agency@verdnatura.es');
it('should check the summary contains the name and userName on the header', async() => { expect(await page.getProperty(selectors.workerSummary.department, 'innerText')).toEqual('CAMARA');
const result = await page.waitToGetProperty(selectors.workerSummary.header, 'innerText'); expect(await page.getProperty(selectors.workerSummary.userId, 'innerText')).toEqual('3');
expect(await page.getProperty(selectors.workerSummary.userName, 'innerText')).toEqual('agency');
expect(result).toEqual('agency agency'); expect(await page.getProperty(selectors.workerSummary.role, 'innerText')).toEqual('agency');
}); expect(await page.getProperty(selectors.workerSummary.extension, 'innerText')).toEqual('1101');
it('should check the summary contains the basic data id', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.id, 'innerText');
expect(result).toEqual('3');
});
it('should check the summary contains the basic data email', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.email, 'innerText');
expect(result).toEqual('agency@verdnatura.es');
});
it('should check the summary contains the basic data department', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.department, 'innerText');
expect(result).toEqual('CAMARA');
});
it('should check the summary contains the user data id', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.userId, 'innerText');
expect(result).toEqual('3');
});
it('should check the summary contains the user data name', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.userName, 'innerText');
expect(result).toEqual('agency');
});
it('should check the summary contains the user data role', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.role, 'innerText');
expect(result).toEqual('agency');
});
it('should check the summary contains the user data extension', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.extension, 'innerText');
expect(result).toEqual('1101');
}); });
}); });

View File

@ -2,13 +2,18 @@ import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
describe('Worker basic data path', () => { describe('Worker basic data path', () => {
const workerId = 1106;
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('hr', 'worker'); await page.loginAndModule('hr', 'worker');
const httpDataResponse = page.waitForResponse(response => {
return response.status() === 200 && response.url().includes(`Workers/${workerId}`);
});
await page.accessToSearchResult('David Charles Haller'); await page.accessToSearchResult('David Charles Haller');
await httpDataResponse;
await page.accessToSection('worker.card.basicData'); await page.accessToSection('worker.card.basicData');
}); });
@ -16,35 +21,20 @@ describe('Worker basic data path', () => {
await browser.close(); await browser.close();
}); });
it('should edit the form', async() => { it('should edit the form and then reload the section and check the data was edited', async() => {
await page.clearInput(selectors.workerBasicData.name); await page.overwrite(selectors.workerBasicData.name, 'David C.');
await page.write(selectors.workerBasicData.name, 'David C.'); await page.overwrite(selectors.workerBasicData.surname, 'H.');
await page.clearInput(selectors.workerBasicData.surname); await page.overwrite(selectors.workerBasicData.phone, '444332211');
await page.write(selectors.workerBasicData.surname, 'H.'); await page.click(selectors.workerBasicData.saveButton);
await page.clearInput(selectors.workerBasicData.phone);
await page.write(selectors.workerBasicData.phone, '444332211');
await page.waitToClick(selectors.workerBasicData.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');
});
it('should reload the section then check the name was edited', async() => {
await page.reloadSection('worker.card.basicData'); await page.reloadSection('worker.card.basicData');
const result = await page.waitToGetProperty(selectors.workerBasicData.name, 'value');
expect(result).toEqual('David C.'); expect(await page.waitToGetProperty(selectors.workerBasicData.name, 'value')).toEqual('David C.');
}); expect(await page.waitToGetProperty(selectors.workerBasicData.surname, 'value')).toEqual('H.');
expect(await page.waitToGetProperty(selectors.workerBasicData.phone, 'value')).toEqual('444332211');
it('should the surname was edited', async() => {
const result = await page.waitToGetProperty(selectors.workerBasicData.surname, 'value');
expect(result).toEqual('H.');
});
it('should the phone was edited', async() => {
const result = await page.waitToGetProperty(selectors.workerBasicData.phone, 'value');
expect(result).toEqual('444332211');
}); });
}); });

View File

@ -16,19 +16,16 @@ describe('Worker pbx path', () => {
await browser.close(); await browser.close();
}); });
it('should receive an error when the extension exceeds 4 characters', async() => { it('should receive an error when the extension exceeds 4 characters and then sucessfully save the changes', async() => {
await page.write(selectors.workerPbx.extension, '55555'); await page.write(selectors.workerPbx.extension, '55555');
await page.waitToClick(selectors.workerPbx.saveButton); await page.click(selectors.workerPbx.saveButton);
const message = await page.waitForSnackbar(); let message = await page.waitForSnackbar();
expect(message.text).toContain('Extension format is invalid'); expect(message.text).toContain('Extension format is invalid');
});
it('should sucessfully save the changes', async() => { await page.overwrite(selectors.workerPbx.extension, '4444');
await page.clearInput(selectors.workerPbx.extension); await page.click(selectors.workerPbx.saveButton);
await page.write(selectors.workerPbx.extension, '4444'); message = await page.waitForSnackbar();
await page.waitToClick(selectors.workerPbx.saveButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved! User must access web'); expect(message.text).toContain('Data saved! User must access web');
}); });

View File

@ -21,43 +21,40 @@ describe('Worker time control path', () => {
const fourPm = '16:00'; const fourPm = '16:00';
const hankPymId = 1107; const hankPymId = 1107;
it('should go to the next month', async() => { it('should go to the next month, go to current month and go 1 month in the past', async() => {
const date = new Date(); let date = new Date();
date.setMonth(date.getMonth() + 1); date.setMonth(date.getMonth() + 1);
const month = date.toLocaleString('default', {month: 'long'}); let month = date.toLocaleString('default', {month: 'long'});
await page.waitToClick(selectors.workerTimeControl.nextMonthButton); await page.click(selectors.workerTimeControl.nextMonthButton);
const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
expect(result).toContain(month); expect(result).toContain(month);
});
it('should go to current month', async() => { date = new Date();
const date = new Date(); month = date.toLocaleString('default', {month: 'long'});
const month = date.toLocaleString('default', {month: 'long'});
await page.waitToClick(selectors.workerTimeControl.previousMonthButton); await page.click(selectors.workerTimeControl.previousMonthButton);
const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
expect(result).toContain(month); expect(result).toContain(month);
});
it('should go 1 month in the past', async() => { date = new Date();
const date = new Date();
date.setMonth(date.getMonth() - 1); date.setMonth(date.getMonth() - 1);
const timestamp = Math.round(date.getTime() / 1000); const timestamp = Math.round(date.getTime() / 1000);
const month = date.toLocaleString('default', {month: 'long'}); month = date.toLocaleString('default', {month: 'long'});
await page.loginAndModule('salesBoss', 'worker'); await page.loginAndModule('salesBoss', 'worker');
await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`); await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`);
await page.waitToClick(selectors.workerTimeControl.secondWeekDay); await page.click(selectors.workerTimeControl.secondWeekDay);
const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
expect(result).toContain(month); expect(result).toContain(month);
}); });
it(`should return error when insert 'out' of first entry`, async() => { it(`should return error when insert 'out' of first entry`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm);
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
@ -68,6 +65,7 @@ describe('Worker time control path', () => {
}); });
it(`should insert 'in' monday`, async() => { it(`should insert 'in' monday`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm);
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in'); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
@ -78,6 +76,7 @@ describe('Worker time control path', () => {
}); });
it(`should insert 'out' monday`, async() => { it(`should insert 'out' monday`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, fourPm); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, fourPm);
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
@ -88,11 +87,13 @@ describe('Worker time control path', () => {
}); });
it(`should check Hank Pym worked 8:20 hours`, async() => { it(`should check Hank Pym worked 8:20 hours`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '08:20 h.'); await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '08:20 h.');
await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '08:20 h.'); await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '08:20 h.');
}); });
it('should remove first entry of monday', async() => { it('should remove first entry of monday', async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitForTextInElement(selectors.workerTimeControl.firstEntryOfMonday, eightAm); await page.waitForTextInElement(selectors.workerTimeControl.firstEntryOfMonday, eightAm);
await page.waitForTextInElement(selectors.workerTimeControl.secondEntryOfMonday, fourPm); await page.waitForTextInElement(selectors.workerTimeControl.secondEntryOfMonday, fourPm);
await page.waitToClick(selectors.workerTimeControl.firstEntryOfMondayDelete); await page.waitToClick(selectors.workerTimeControl.firstEntryOfMondayDelete);
@ -103,13 +104,16 @@ describe('Worker time control path', () => {
}); });
it(`should be the 'out' the first entry of monday`, async() => { it(`should be the 'out' the first entry of monday`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText');
expect(result).toEqual(fourPm); expect(result).toEqual(fourPm);
}); });
it('should change week of month', async() => { it('should change week of month', async() => {
await page.waitToClick(selectors.workerTimeControl.thrirdWeekDay); await page.click(selectors.workerTimeControl.thrirdWeekDay);
await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '00:00 h.'); const result = await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText');
expect(result).toEqual('00:00 h.');
}); });
}); });

View File

@ -1,16 +1,25 @@
/* eslint-disable max-len */
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
describe('Worker calendar path', () => { describe('Worker calendar path', () => {
let reasonableTimeBetweenClicks = 400; const reasonableTimeBetweenClicks = 300;
const date = new Date();
const lastYear = (date.getFullYear() - 1).toString();
let browser; let browser;
let page; let page;
async function accessAs(user) {
await page.loginAndModule(user, 'worker');
await page.accessToSearchResult('Charles Xavier');
await page.accessToSection('worker.card.calendar');
}
beforeAll(async() => { beforeAll(async() => {
browser = await getBrowser(); browser = await getBrowser();
page = browser.page; page = browser.page;
await page.loginAndModule('hr', 'worker'); accessAs('hr');
await page.accessToSearchResult('Charles Xavier');
await page.accessToSection('worker.card.calendar');
}); });
afterAll(async() => { afterAll(async() => {
@ -21,48 +30,40 @@ describe('Worker calendar path', () => {
it('should set two days as holidays on the calendar and check the total holidays increased by 1.5', async() => { it('should set two days as holidays on the calendar and check the total holidays increased by 1.5', async() => {
await page.waitToClick(selectors.workerCalendar.holidays); await page.waitToClick(selectors.workerCalendar.holidays);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); await page.click(selectors.workerCalendar.penultimateMondayOfJanuary);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.absence); await page.click(selectors.workerCalendar.absence);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.lastMondayOfMarch); await page.click(selectors.workerCalendar.lastMondayOfMarch);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.halfHoliday); await page.click(selectors.workerCalendar.halfHoliday);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.fistMondayOfMay); await page.click(selectors.workerCalendar.fistMondayOfMay);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.furlough); await page.click(selectors.workerCalendar.furlough);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.secondTuesdayOfMay); await page.click(selectors.workerCalendar.secondTuesdayOfMay);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.secondWednesdayOfMay); await page.click(selectors.workerCalendar.secondWednesdayOfMay);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.secondThursdayOfMay); await page.click(selectors.workerCalendar.secondThursdayOfMay);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.halfFurlough); await page.click(selectors.workerCalendar.halfFurlough);
await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.secondFridayOfJun);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.click(selectors.workerCalendar.secondFridayOfJun);
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 1.5 ');
expect(result).toContain(' 1.5 ');
}); });
}); });
describe(`as salesBoss`, () => { describe(`as salesBoss`, () => {
it(`should log in and get to Charles Xavier's calendar`, async() => { it(`should log in, get to Charles Xavier's calendar, undo what was done here, and check the total holidays used are back to what it was`, async() => {
await page.loginAndModule('salesBoss', 'worker'); accessAs('salesBoss');
await page.accessToSearchResult('Charles Xavier');
await page.accessToSection('worker.card.calendar');
});
it('should undo what was done here', async() => {
await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.holidays); await page.waitToClick(selectors.workerCalendar.holidays);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary);
@ -90,45 +91,24 @@ describe('Worker calendar path', () => {
await page.waitToClick(selectors.workerCalendar.halfFurlough); await page.waitToClick(selectors.workerCalendar.halfFurlough);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.secondFridayOfJun); await page.waitToClick(selectors.workerCalendar.secondFridayOfJun);
});
it('should check the total holidays used are back to what it was', async() => { expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 ');
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
expect(result).toContain(' 0 ');
}); });
}); });
describe(`as Charles Xavier`, () => { describe(`as Charles Xavier`, () => {
it(`should log in and get to his calendar`, async() => { it('should log in and get to his calendar, make a futile attempt to add holidays, check the total holidays used are now the initial ones and use the year selector to go to the previous year', async() => {
await page.loginAndModule('CharlesXavier', 'worker'); accessAs('CharlesXavier');
await page.accessToSearchResult('Charles Xavier');
await page.accessToSection('worker.card.calendar');
});
it('should make a futile attempt to add holidays', async() => {
await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.holidays); await page.waitToClick(selectors.workerCalendar.holidays);
await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitForTimeout(reasonableTimeBetweenClicks);
await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary);
});
it('should check the total holidays used are now the initial ones', async() => { await page.click(selectors.workerCalendar.penultimateMondayOfJanuary);
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
expect(result).toContain(' 0 '); expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 ');
});
it('should use the year selector to go to the previous year', async() => {
const date = new Date();
const lastYear = (date.getFullYear() - 1).toString();
await page.autocompleteSearch(selectors.workerCalendar.year, lastYear); await page.autocompleteSearch(selectors.workerCalendar.year, lastYear);
await page.waitForTimeout(reasonableTimeBetweenClicks); expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 ');
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
expect(result).toContain(' 0 ');
}); });
}); });
}); });

View File

@ -35,6 +35,7 @@ describe('Item Edit basic data path', () => {
await page.waitToClick(selectors.itemBasicData.isActiveCheckbox); await page.waitToClick(selectors.itemBasicData.isActiveCheckbox);
await page.waitToClick(selectors.itemBasicData.priceInKgCheckbox); await page.waitToClick(selectors.itemBasicData.priceInKgCheckbox);
await page.waitToClick(selectors.itemBasicData.isFragile); await page.waitToClick(selectors.itemBasicData.isFragile);
await page.write(selectors.itemBasicData.packingOut, '5');
await page.waitToClick(selectors.itemBasicData.submitBasicDataButton); await page.waitToClick(selectors.itemBasicData.submitBasicDataButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
@ -128,4 +129,11 @@ describe('Item Edit basic data path', () => {
expect(result).toBe('checked'); 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

@ -127,8 +127,8 @@ describe('Item regularize path', () => {
await page.waitForState('ticket.index'); await page.waitForState('ticket.index');
}); });
it('should search for the ticket with id 31 once again', async() => { it('should search for the ticket missing once again', async() => {
await page.accessToSearchResult('31'); await page.accessToSearchResult('Missing');
await page.waitForState('ticket.card.summary'); await page.waitForState('ticket.card.summary');
}); });

View File

@ -32,14 +32,17 @@ describe('Ticket expeditions and log path', () => {
it(`should confirm the expedition deleted is shown now in the ticket log`, async() => { it(`should confirm the expedition deleted is shown now in the ticket log`, async() => {
await page.accessToSection('ticket.card.log'); await page.accessToSection('ticket.card.log');
const firstLogEntry = await page const user = await page
.waitToGetProperty(selectors.ticketLog.firstLogEntry, 'innerText'); .waitToGetProperty(selectors.ticketLog.user, 'innerText');
const action = await page
.waitToGetProperty(selectors.ticketLog.action, 'innerText');
const id = await page const id = await page
.waitToGetProperty(selectors.ticketLog.id, 'innerText'); .waitToGetProperty(selectors.ticketLog.id, 'innerText');
expect(firstLogEntry).toContain('production'); expect(user).toContain('production');
expect(firstLogEntry).toContain('Deletes'); expect(action).toContain('Deletes');
expect(id).toEqual('2'); expect(id).toEqual('2');
}); });
}); });

View File

@ -55,6 +55,6 @@ describe('Ticket log path', () => {
const result = await page.waitToGetProperty(selectors.ticketLog.firstTD, 'innerText'); const result = await page.waitToGetProperty(selectors.ticketLog.firstTD, 'innerText');
expect(result.length).toBeGreaterThan('20'); expect(result.length).toBeGreaterThan('15');
}); });
}); });

View File

@ -16,9 +16,6 @@ describe('Ticket Future path', () => {
await browser.close(); await browser.close();
}); });
const now = new Date();
const tomorrow = new Date(now.getDate() + 1);
it('should show errors snackbar because of the required data', async() => { it('should show errors snackbar because of the required data', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.warehouseFk); await page.clearInput(selectors.ticketFuture.warehouseFk);
@ -27,20 +24,6 @@ describe('Ticket Future path', () => {
expect(message.text).toContain('warehouseFk is a required argument'); expect(message.text).toContain('warehouseFk is a required argument');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.litersMax);
await page.waitToClick(selectors.ticketFuture.submit);
message = await page.waitForSnackbar();
expect(message.text).toContain('litersMax is a required argument');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.linesMax);
await page.waitToClick(selectors.ticketFuture.submit);
message = await page.waitForSnackbar();
expect(message.text).toContain('linesMax is a required argument');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.futureDated); await page.clearInput(selectors.ticketFuture.futureDated);
await page.waitToClick(selectors.ticketFuture.submit); await page.waitToClick(selectors.ticketFuture.submit);
@ -62,44 +45,13 @@ describe('Ticket Future path', () => {
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
}); });
it('should search with the origin shipped today', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.pickDate(selectors.ticketFuture.shipped, now);
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
});
it('should search with the origin shipped tomorrow', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.pickDate(selectors.ticketFuture.shipped, tomorrow);
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
});
it('should search with the destination shipped today', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.shipped);
await page.pickDate(selectors.ticketFuture.tfShipped, now);
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
});
it('should search with the destination shipped tomorrow', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.pickDate(selectors.ticketFuture.tfShipped, tomorrow);
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
});
it('should search with the origin IPT', async() => { it('should search with the origin IPT', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.shipped);
await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt); await page.clearInput(selectors.ticketFuture.ipt);
await page.clearInput(selectors.ticketFuture.tfIpt); await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.state);
await page.clearInput(selectors.ticketFuture.tfState); await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal'); await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal');
await page.waitToClick(selectors.ticketFuture.submit); await page.waitToClick(selectors.ticketFuture.submit);
@ -109,14 +61,12 @@ describe('Ticket Future path', () => {
it('should search with the destination IPT', async() => { it('should search with the destination IPT', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.shipped);
await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt); await page.clearInput(selectors.ticketFuture.ipt);
await page.clearInput(selectors.ticketFuture.tfIpt); await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.state);
await page.clearInput(selectors.ticketFuture.tfState); await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.tfIpt, 'Horizontal'); await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal');
await page.waitToClick(selectors.ticketFuture.submit); await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
}); });
@ -124,12 +74,10 @@ describe('Ticket Future path', () => {
it('should search with the origin grouped state', async() => { it('should search with the origin grouped state', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.shipped);
await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt); await page.clearInput(selectors.ticketFuture.ipt);
await page.clearInput(selectors.ticketFuture.tfIpt); await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.state);
await page.clearInput(selectors.ticketFuture.tfState); await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); await page.autocompleteSearch(selectors.ticketFuture.state, 'Free');
await page.waitToClick(selectors.ticketFuture.submit); await page.waitToClick(selectors.ticketFuture.submit);
@ -139,24 +87,20 @@ describe('Ticket Future path', () => {
it('should search with the destination grouped state', async() => { it('should search with the destination grouped state', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.shipped);
await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt); await page.clearInput(selectors.ticketFuture.ipt);
await page.clearInput(selectors.ticketFuture.tfIpt); await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.state);
await page.clearInput(selectors.ticketFuture.tfState); await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.tfState, 'Free'); await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free');
await page.waitToClick(selectors.ticketFuture.submit); await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.shipped);
await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt); await page.clearInput(selectors.ticketFuture.ipt);
await page.clearInput(selectors.ticketFuture.tfIpt); await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.state);
await page.clearInput(selectors.ticketFuture.tfState); await page.clearInput(selectors.ticketFuture.futureState);
await page.waitToClick(selectors.ticketFuture.submit); await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
@ -176,7 +120,7 @@ describe('Ticket Future path', () => {
it('should search in smart-table with an ID Destination', async() => { it('should search in smart-table with an ID Destination', async() => {
await page.waitToClick(selectors.ticketFuture.tableButtonSearch); await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
await page.write(selectors.ticketFuture.tableTfId, '12'); await page.write(selectors.ticketFuture.tableFutureId, '12');
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.ticketFuture.table, 5); await page.waitForNumberOfElements(selectors.ticketFuture.table, 5);
@ -199,7 +143,7 @@ describe('Ticket Future path', () => {
it('should search in smart-table with an IPT Destination', async() => { it('should search in smart-table with an IPT Destination', async() => {
await page.waitToClick(selectors.ticketFuture.tableButtonSearch); await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
await page.autocompleteSearch(selectors.ticketFuture.tableTfIpt, 'Vertical'); await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Vertical');
await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); await page.waitForNumberOfElements(selectors.ticketFuture.table, 1);
await page.waitToClick(selectors.ticketFuture.tableButtonSearch); await page.waitToClick(selectors.ticketFuture.tableButtonSearch);

View File

@ -0,0 +1,162 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Ticket Advance path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('employee', 'ticket');
await page.accessToSection('ticket.advance');
});
afterAll(async() => {
await browser.close();
});
it('should show errors snackbar because of the required data', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.warehouseFk);
await page.waitToClick(selectors.ticketAdvance.submit);
let message = await page.waitForSnackbar();
expect(message.text).toContain('warehouseFk is a required argument');
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.dateToAdvance);
await page.waitToClick(selectors.ticketAdvance.submit);
message = await page.waitForSnackbar();
expect(message.text).toContain('dateToAdvance is a required argument');
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.dateFuture);
await page.waitToClick(selectors.ticketAdvance.submit);
message = await page.waitForSnackbar();
expect(message.text).toContain('dateFuture is a required argument');
});
it('should search with the required data', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search with the origin IPT', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal');
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.ipt);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search with the destination IPT', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal');
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.futureIpt);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search with the origin grouped state', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.autocompleteSearch(selectors.ticketAdvance.futureState, 'Free');
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.futureState);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search with the destination grouped state', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.autocompleteSearch(selectors.ticketAdvance.state, 'Free');
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.state);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search in smart-table with an IPT Origin', async() => {
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical');
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search in smart-table with an IPT Destination', async() => {
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical');
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search in smart-table with stock', async() => {
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.write(selectors.ticketAdvance.tableStock, '5');
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 2);
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search in smart-table with especified Lines', async() => {
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.write(selectors.ticketAdvance.tableLines, '0');
await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search in smart-table with especified Liters', async() => {
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.write(selectors.ticketAdvance.tableLiters, '0');
await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should check the three last tickets and move to the future', async() => {
await page.waitToClick(selectors.ticketAdvance.multiCheck);
await page.waitToClick(selectors.ticketAdvance.moveButton);
await page.waitToClick(selectors.ticketAdvance.acceptButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Tickets moved successfully!');
});
});

View File

@ -70,8 +70,8 @@ describe('Supplier basic data path', () => {
}); });
it('should check the changes have been recorded', async() => { it('should check the changes have been recorded', async() => {
const result = await page.waitToGetProperty('#newInstance:nth-child(3)', 'innerText'); const result = await page.waitToGetProperty('vn-tr table tr:nth-child(3) td.after', 'innerText');
expect(result).toEqual('note Some notes'); expect(result).toEqual('Some notes');
}); });
}); });

View File

@ -14,6 +14,7 @@ export default class CrudModel extends ModelProxy {
this.$q = $q; this.$q = $q;
this.primaryKey = 'id'; this.primaryKey = 'id';
this.autoLoad = false; this.autoLoad = false;
this.page = 1;
} }
$onInit() { $onInit() {
@ -125,13 +126,20 @@ export default class CrudModel extends ModelProxy {
} }
} }
loadMore() { loadMore(append) {
if (!this.moreRows) if (!this.moreRows)
return this.$q.resolve(); return this.$q.resolve();
let filter = Object.assign({}, this.currentFilter); const filter = Object.assign({}, this.currentFilter);
filter.skip = this.orgData ? this.orgData.length : 0; if (append)
return this.sendRequest(filter, true); filter.skip = this.orgData ? this.orgData.length : 0;
if (!append) {
this.page += 1;
filter.limit = this.page * this.limit;
}
return this.sendRequest(filter, append);
} }
clear() { clear() {

View File

@ -148,7 +148,7 @@ describe('Component vnCrudModel', () => {
controller.moreRows = true; controller.moreRows = true;
controller.loadMore(); controller.loadMore(true);
expect(controller.sendRequest).toHaveBeenCalledWith({'skip': 2}, true); expect(controller.sendRequest).toHaveBeenCalledWith({'skip': 2}, true);
}); });

View File

@ -212,12 +212,12 @@ export default class DropDown extends Popover {
&& !this.model.isLoading; && !this.model.isLoading;
if (shouldLoad) if (shouldLoad)
this.model.loadMore(); this.model.loadMore(true);
} }
onLoadMoreClick(event) { onLoadMoreClick(event) {
if (event.defaultPrevented) return; if (event.defaultPrevented) return;
this.model.loadMore(); this.model.loadMore(true);
} }
onContainerClick(event) { onContainerClick(event) {

View File

@ -26,7 +26,7 @@ class Icon {
Icon.$inject = ['$attrs']; Icon.$inject = ['$attrs'];
ngModule.vnComponent('vnIcon', { ngModule.vnComponent('vnIcon', {
template: '<i class="{{::$ctrl.iconClass}} unselectable">{{::$ctrl.iconContent}}</i>', template: '<i class="{{::$ctrl.iconClass}} unselectable notranslate">{{::$ctrl.iconContent}}</i>',
controller: Icon, controller: Icon,
bindings: { bindings: {
icon: '@' icon: '@'

View File

@ -374,9 +374,10 @@ export class Paginable {
/** /**
* When limit is enabled, loads the next set of rows. * When limit is enabled, loads the next set of rows.
* *
* @param {Boolean} append - Whether should append new data
* @return {Promise} The request promise * @return {Promise} The request promise
*/ */
loadMore() { loadMore(append) {
return Promise.resolve(); return Promise.resolve(append);
} }
} }

View File

@ -73,7 +73,7 @@ class Pagination extends Component {
if (shouldLoad) { if (shouldLoad) {
this.nLoads++; this.nLoads++;
this.model.loadMore(); this.model.loadMore(false);
this.$.$apply(); this.$.$apply();
} }
} }
@ -82,7 +82,7 @@ class Pagination extends Component {
if (this.maxLoads > 0 && this.nLoads == this.maxLoads) if (this.maxLoads > 0 && this.nLoads == this.maxLoads)
this.nLoads = 0; this.nLoads = 0;
this.model.loadMore(); this.model.loadMore(false);
} }
$onDestroy() { $onDestroy() {

View File

@ -147,7 +147,7 @@ export default class SmartTable extends Component {
for (const column of this.columns) { for (const column of this.columns) {
if (viewConfig.configuration[column.field] == false) { if (viewConfig.configuration[column.field] == false) {
const baseSelector = `smart-table[view-config-id="${this.viewConfigId}"] table`; const baseSelector = `smart-table[view-config-id="${this.viewConfigId}"] table`;
selectors.push(`${baseSelector} thead > tr > th:nth-child(${column.index + 1})`); selectors.push(`${baseSelector} thead > tr:not([second-header]) > th:nth-child(${column.index + 1})`);
selectors.push(`${baseSelector} tbody > tr > td:nth-child(${column.index + 1})`); selectors.push(`${baseSelector} tbody > tr > td:nth-child(${column.index + 1})`);
} }
} }
@ -235,7 +235,7 @@ export default class SmartTable extends Component {
} }
registerColumns() { registerColumns() {
const header = this.element.querySelector('thead > tr'); const header = this.element.querySelector('thead > tr:not([second-header])');
if (!header) return; if (!header) return;
const columns = header.querySelectorAll('th'); const columns = header.querySelectorAll('th');
@ -254,7 +254,7 @@ export default class SmartTable extends Component {
} }
emptyDataRows() { emptyDataRows() {
const header = this.element.querySelector('thead > tr'); const header = this.element.querySelector('thead > tr:not([second-header])');
const columns = header.querySelectorAll('th'); const columns = header.querySelectorAll('th');
const tbody = this.element.querySelector('tbody'); const tbody = this.element.querySelector('tbody');
if (tbody) { if (tbody) {
@ -333,7 +333,7 @@ export default class SmartTable extends Component {
} }
displaySearch() { displaySearch() {
const header = this.element.querySelector('thead > tr'); const header = this.element.querySelector('thead > tr:not([second-header])');
if (!header) return; if (!header) return;
const tbody = this.element.querySelector('tbody'); const tbody = this.element.querySelector('tbody');

View File

@ -8,6 +8,16 @@ smart-table table {
& > thead { & > thead {
border-bottom: $border; border-bottom: $border;
& > tr[second-header] {
& > th
{
text-align: center;
border-bottom-style: groove;
font-weight: bold;
text-transform: uppercase;
}
}
& > * > th { & > * > th {
font-weight: normal; font-weight: normal;
} }
@ -60,6 +70,9 @@ smart-table table {
vertical-align: middle; vertical-align: middle;
} }
} }
&[separator]{
border-left-style: groove;
}
vn-icon.bright, i.bright { vn-icon.bright, i.bright {
color: #f7931e; color: #f7931e;
} }
@ -108,4 +121,4 @@ smart-table table {
font-size: 1.375rem; font-size: 1.375rem;
text-align: center; text-align: center;
} }
} }

View File

@ -29,7 +29,7 @@ vn-table {
& > tbody { & > tbody {
display: table-row-group; display: table-row-group;
} }
& > vn-tfoot, & > vn-tfoot,
& > .vn-tfoot, & > .vn-tfoot,
& > tfoot { & > tfoot {
border-top: $border; border-top: $border;
@ -42,7 +42,7 @@ vn-table {
height: 48px; height: 48px;
} }
vn-thead, .vn-thead, vn-thead, .vn-thead,
vn-tbody, .vn-tbody, vn-tbody, .vn-tbody,
vn-tfoot, .vn-tfoot, vn-tfoot, .vn-tfoot,
thead, tbody, tfoot { thead, tbody, tfoot {
& > * { & > * {
@ -153,6 +153,18 @@ vn-table {
background-color: $color-font-bg-dark; background-color: $color-font-bg-dark;
color: $color-font-bg; color: $color-font-bg;
} }
&.dark-notice {
background-color: $color-notice;
color: $color-font-bg;
}
&.yellow {
background-color: $color-yellow;
color: $color-font-bg;
}
&.pink {
background-color: $color-pink;
color: $color-font-bg;
}
} }
vn-icon-menu { vn-icon-menu {
display: inline-block; display: inline-block;
@ -194,7 +206,7 @@ vn-table.scrollable > .vn-table,
} }
vn-thead th, vn-thead th,
vn-thead vn-th, vn-thead vn-th,
thead vn-th, thead vn-th,
thead th { thead th {
border-bottom: $border; border-bottom: $border;
@ -217,4 +229,4 @@ vn-table.scrollable.lg,
.tableWrapper { .tableWrapper {
overflow-x: auto; overflow-x: auto;
} }

View File

@ -24,7 +24,7 @@ export default class Auth {
initialize() { initialize() {
let criteria = { let criteria = {
to: state => { to: state => {
const outLayout = ['login', 'recoverPassword', 'resetPassword']; const outLayout = ['login', 'recover-password', 'reset-password'];
return !outLayout.some(ol => ol == state.name); return !outLayout.some(ol => ol == state.name);
} }
}; };

View File

@ -29,6 +29,7 @@ export default class Modules {
const module = { const module = {
name: mod.name || mod.module, name: mod.name || mod.module,
code: mod.module,
icon: mod.icon || null, icon: mod.icon || null,
route, route,
keyBind keyBind

View File

@ -101,6 +101,8 @@ $color-marginal: #222;
$color-success: #a3d131; $color-success: #a3d131;
$color-notice: #32b1ce; $color-notice: #32b1ce;
$color-alert: #fa3939; $color-alert: #fa3939;
$color-pink: #ff99cc;
$color-yellow: #ffff00;
$color-button: $color-secondary; $color-button: $color-secondary;
$color-spacer: rgba(255, 255, 255, .3); $color-spacer: rgba(255, 255, 255, .3);

View File

@ -1,7 +1,7 @@
{ {
"name": "salix-front", "name": "salix-front",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 1, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
@ -25,8 +25,7 @@
}, },
"node_modules/@uirouter/angularjs": { "node_modules/@uirouter/angularjs": {
"version": "1.0.30", "version": "1.0.30",
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz", "license": "MIT",
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
"dependencies": { "dependencies": {
"@uirouter/core": "6.0.8" "@uirouter/core": "6.0.8"
}, },
@ -39,17 +38,14 @@
}, },
"node_modules/@uirouter/core": { "node_modules/@uirouter/core": {
"version": "6.0.8", "version": "6.0.8",
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz", "license": "MIT",
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw==",
"engines": { "engines": {
"node": ">=4.0.0" "node": ">=4.0.0"
} }
}, },
"node_modules/angular": { "node_modules/angular": {
"version": "1.8.3", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz", "license": "MIT"
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
}, },
"node_modules/angular-animate": { "node_modules/angular-animate": {
"version": "1.8.2", "version": "1.8.2",
@ -67,8 +63,7 @@
}, },
"node_modules/angular-translate": { "node_modules/angular-translate": {
"version": "2.19.0", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz", "license": "MIT",
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
"dependencies": { "dependencies": {
"angular": "^1.8.0" "angular": "^1.8.0"
}, },
@ -78,8 +73,7 @@
}, },
"node_modules/angular-translate-loader-partial": { "node_modules/angular-translate-loader-partial": {
"version": "2.19.0", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz", "license": "MIT",
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
"dependencies": { "dependencies": {
"angular-translate": "~2.19.0" "angular-translate": "~2.19.0"
} }
@ -126,8 +120,7 @@
}, },
"node_modules/moment": { "node_modules/moment": {
"version": "2.29.4", "version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "license": "MIT",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": { "engines": {
"node": "*" "node": "*"
} }
@ -172,73 +165,51 @@
"dependencies": { "dependencies": {
"@uirouter/angularjs": { "@uirouter/angularjs": {
"version": "1.0.30", "version": "1.0.30",
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz",
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
"requires": { "requires": {
"@uirouter/core": "6.0.8" "@uirouter/core": "6.0.8"
} }
}, },
"@uirouter/core": { "@uirouter/core": {
"version": "6.0.8", "version": "6.0.8"
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz",
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw=="
}, },
"angular": { "angular": {
"version": "1.8.3", "version": "1.8.3"
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw=="
}, },
"angular-animate": { "angular-animate": {
"version": "1.8.2", "version": "1.8.2"
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
}, },
"angular-moment": { "angular-moment": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
"requires": { "requires": {
"moment": ">=2.8.0 <3.0.0" "moment": ">=2.8.0 <3.0.0"
} }
}, },
"angular-translate": { "angular-translate": {
"version": "2.19.0", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz",
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
"requires": { "requires": {
"angular": "^1.8.0" "angular": "^1.8.0"
} }
}, },
"angular-translate-loader-partial": { "angular-translate-loader-partial": {
"version": "2.19.0", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz",
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
"requires": { "requires": {
"angular-translate": "~2.19.0" "angular-translate": "~2.19.0"
} }
}, },
"argparse": { "argparse": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": { "requires": {
"sprintf-js": "~1.0.2" "sprintf-js": "~1.0.2"
} }
}, },
"croppie": { "croppie": {
"version": "2.6.5", "version": "2.6.5"
"resolved": "https://registry.npmjs.org/croppie/-/croppie-2.6.5.tgz",
"integrity": "sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ=="
}, },
"esprima": { "esprima": {
"version": "4.0.1", "version": "4.0.1"
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
}, },
"js-yaml": { "js-yaml": {
"version": "3.14.1", "version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"requires": { "requires": {
"argparse": "^1.0.7", "argparse": "^1.0.7",
"esprima": "^4.0.0" "esprima": "^4.0.0"
@ -246,39 +217,27 @@
}, },
"mg-crud": { "mg-crud": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
"integrity": "sha512-mAR6t0aQHKnT0QHKHpLOi0kNPZfO36iMpIoiLjFHxuio6mIJyuveBJ4VNlNXJRxLh32/FLADEb41/sYo7QUKFw==",
"requires": { "requires": {
"angular": "^1.6.1" "angular": "^1.6.1"
} }
}, },
"moment": { "moment": {
"version": "2.29.4", "version": "2.29.4"
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
}, },
"oclazyload": { "oclazyload": {
"version": "0.6.3", "version": "0.6.3"
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
"integrity": "sha512-HpOSYUgjtt6sTB/C6+FWsExR+9HCnXKsUA96RWkDXfv11C8Cc9X2DlR0WIZwFIiG6FQU0pwB5dhoYyut8bFAOQ=="
}, },
"require-yaml": { "require-yaml": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
"integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==",
"requires": { "requires": {
"js-yaml": "^4.1.0" "js-yaml": ""
}, },
"dependencies": { "dependencies": {
"argparse": { "argparse": {
"version": "2.0.1", "version": "2.0.1"
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
}, },
"js-yaml": { "js-yaml": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"requires": { "requires": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
} }
@ -286,14 +245,10 @@
} }
}, },
"sprintf-js": { "sprintf-js": {
"version": "1.0.3", "version": "1.0.3"
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
}, },
"validator": { "validator": {
"version": "6.3.0", "version": "6.3.0"
"resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz",
"integrity": "sha512-BylxTwhqwjQI5MDJF7amCy/L0ejJO+74DvCsLV52Lq3+3bhVcVMKqNqOiNcQJm2G48u9EAcw4xFERAmFbwXM9Q=="
} }
} }
} }

View File

@ -1,8 +1,3 @@
<vn-layout <ui-view></ui-view>
ng-if="$ctrl.showLayout">
</vn-layout>
<vn-out-layout
ng-if="!$ctrl.showLayout">
</vn-out-layout>
<vn-snackbar vn-id="snackbar"></vn-snackbar> <vn-snackbar vn-id="snackbar"></vn-snackbar>
<vn-debug-info></vn-debug-info> <vn-debug-info></vn-debug-info>

View File

@ -19,12 +19,6 @@ export default class App extends Component {
this.vnApp.logger = this; this.vnApp.logger = this;
} }
get showLayout() {
const state = this.$state.current.name || this.$location.$$path.substring(1).replace('/', '.');
const outLayout = ['login', 'recoverPassword', 'resetPassword'];
return state && !outLayout.some(ol => ol == state);
}
$onDestroy() { $onDestroy() {
this.deregisterCallback(); this.deregisterCallback();
this.vnApp.logger = null; this.vnApp.logger = null;

View File

@ -33,7 +33,9 @@ export default class Controller extends Component {
if (!res.data.length) return; if (!res.data.length) return;
for (let starredModule of res.data) { for (let starredModule of res.data) {
const module = this.modules.find(mod => mod.name === starredModule.moduleFk); let moduleName = starredModule.moduleFk;
if (moduleName === 'customer') moduleName = 'client';
const module = this.modules.find(mod => mod.code === moduleName);
if (module) { if (module) {
module.starred = true; module.starred = true;
module.position = starredModule.position; module.position = starredModule.position;
@ -47,8 +49,10 @@ export default class Controller extends Component {
if (event.defaultPrevented) return; if (event.defaultPrevented) return;
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
let moduleName = module.code;
if (moduleName === 'client') moduleName = 'customer';
const params = {moduleName: module.name}; const params = {moduleName};
const query = `starredModules/toggleStarredModule`; const query = `starredModules/toggleStarredModule`;
this.$http.post(query, params).then(res => { this.$http.post(query, params).then(res => {
if (res.data) { if (res.data) {
@ -84,13 +88,16 @@ export default class Controller extends Component {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
const params = {moduleName: module.name, direction: direction}; let moduleName = module.code;
if (moduleName === 'client') moduleName = 'customer';
const params = {moduleName: moduleName, direction: direction};
const query = `starredModules/setPosition`; const query = `starredModules/setPosition`;
this.$http.post(query, params).then(res => { this.$http.post(query, params).then(res => {
if (res.data) { if (res.data) {
module.position = res.data.movingModule.position; module.position = res.data.movingModule.position;
this.modules.forEach(mod => { this.modules.forEach(mod => {
if (mod.name == res.data.pushedModule.moduleFk) if (mod.code == res.data.pushedModule.moduleFk)
mod.position = res.data.pushedModule.position; mod.position = res.data.pushedModule.position;
}); });
this.vnApp.showSuccess(this.$t('Data saved!')); this.vnApp.showSuccess(this.$t('Data saved!'));

View File

@ -19,7 +19,7 @@ describe('Salix Component vnHome', () => {
describe('getStarredModules()', () => { describe('getStarredModules()', () => {
it('should not set any of the modules as starred if there are no starred modules for the user', () => { it('should not set any of the modules as starred if there are no starred modules for the user', () => {
const expectedResponse = []; const expectedResponse = [];
controller._modules = [{module: 'client', name: 'Clients'}]; controller._modules = [{code: 'client', name: 'Clients'}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse); $httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse);
$httpBackend.expectGET('starredModules/getStarredModules').respond(expectedResponse); $httpBackend.expectGET('starredModules/getStarredModules').respond(expectedResponse);
@ -31,8 +31,8 @@ describe('Salix Component vnHome', () => {
}); });
it('should set the example module as starred since its the starred module for the user', () => { it('should set the example module as starred since its the starred module for the user', () => {
const expectedResponse = [{id: 1, moduleFk: 'Clients', workerFk: 9}]; const expectedResponse = [{id: 1, moduleFk: 'customer', workerFk: 9}];
controller._modules = [{module: 'client', name: 'Clients'}]; controller._modules = [{code: 'client', name: 'Clients'}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse); $httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse);
$httpBackend.expectGET('starredModules/getStarredModules').respond(expectedResponse); $httpBackend.expectGET('starredModules/getStarredModules').respond(expectedResponse);
@ -48,7 +48,7 @@ describe('Salix Component vnHome', () => {
it(`should set the received module as starred if it wasn't starred`, () => { it(`should set the received module as starred if it wasn't starred`, () => {
const expectedResponse = [{id: 1, moduleFk: 'Clients', workerFk: 9}]; const expectedResponse = [{id: 1, moduleFk: 'Clients', workerFk: 9}];
const event = new Event('target'); const event = new Event('target');
controller._modules = [{module: 'client', name: 'Clients'}]; controller._modules = [{code: 'client', name: 'Clients'}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse); $httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse);
$httpBackend.expectPOST('starredModules/toggleStarredModule').respond(expectedResponse); $httpBackend.expectPOST('starredModules/toggleStarredModule').respond(expectedResponse);
@ -61,7 +61,7 @@ describe('Salix Component vnHome', () => {
it('should set the received module as regular if it was starred', () => { it('should set the received module as regular if it was starred', () => {
const event = new Event('target'); const event = new Event('target');
controller._modules = [{module: 'client', name: 'Clients', starred: true}]; controller._modules = [{code: 'client', name: 'Clients', starred: true}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond([]); $httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond([]);
$httpBackend.expectPOST('starredModules/toggleStarredModule').respond(undefined); $httpBackend.expectPOST('starredModules/toggleStarredModule').respond(undefined);
@ -76,18 +76,18 @@ describe('Salix Component vnHome', () => {
describe('moveModule()', () => { describe('moveModule()', () => {
it('should perform a query to setPosition and the apply the position to the moved and pushed modules', () => { it('should perform a query to setPosition and the apply the position to the moved and pushed modules', () => {
const starredModules = [ const starredModules = [
{id: 1, moduleFk: 'Clients', workerFk: 9}, {id: 1, moduleFk: 'customer', workerFk: 9},
{id: 2, moduleFk: 'Orders', workerFk: 9} {id: 2, moduleFk: 'order', workerFk: 9}
]; ];
const movedModules = { const movedModules = {
movingModule: {position: 2, moduleFk: 'Clients'}, movingModule: {position: 2, moduleFk: 'customer'},
pushedModule: {position: 1, moduleFk: 'Orders'} pushedModule: {position: 1, moduleFk: 'order'}
}; };
const event = new Event('target'); const event = new Event('target');
controller._modules = [ controller._modules = [
{module: 'client', name: 'Clients', position: 1}, {code: 'client', name: 'Clients', position: 1},
{module: 'orders', name: 'Orders', position: 2} {code: 'order', name: 'Orders', position: 2}
]; ];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(starredModules); $httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(starredModules);

View File

@ -5,10 +5,10 @@ import './descriptor-popover';
import './home/home'; import './home/home';
import './layout'; import './layout';
import './left-menu/left-menu'; import './left-menu/left-menu';
import './login/index'; import './login';
import './login/login'; import './outLayout';
import './login/recover-password'; import './recover-password';
import './login/reset-password'; import './reset-password';
import './module-card'; import './module-card';
import './module-main'; import './module-main';
import './side-menu/side-menu'; import './side-menu/side-menu';
@ -19,3 +19,4 @@ import './user-popover';
import './upload-photo'; import './upload-photo';
import './bank-entity'; import './bank-entity';
import './log'; import './log';
import './sendSms';

View File

@ -1,10 +1,12 @@
<vn-crud-model <vn-crud-model
vn-id="model" vn-id="model"
url="{{$ctrl.url}}" url="{{$ctrl.url}}"
filter="$ctrl.filter" filter="$ctrl.filter"
link="{originFk: $ctrl.originId}" link="{originFk: $ctrl.originId}"
data="$ctrl.logs" where="{changedModel: $ctrl.changedModel,
limit="20" changedModelId: $ctrl.changedModelId}"
data="$ctrl.logs"
limit="20"
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-data-viewer model="model" class="vn-w-xl"> <vn-data-viewer model="model" class="vn-w-xl">
@ -13,81 +15,53 @@
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th field="creationDate">Date</vn-th> <vn-th field="creationDate">Date</vn-th>
<vn-th field="userFk" class="expendable" shrink>Author</vn-th> <vn-th field="userFk" shrink>User</vn-th>
<vn-th field="changedModel" class="expendable">Model</vn-th> <vn-th field="changedModel" ng-if="$ctrl.showModelName" shrink>Model</vn-th>
<vn-th field="action" class="expendable" shrink>Action</vn-th> <vn-th field="action" shrink>Action</vn-th>
<vn-th field="changedModelValue" class="expendable">Name</vn-th> <vn-th field="changedModelValue" ng-if="$ctrl.showModelName">Name</vn-th>
<vn-th expand>Before</vn-th> <vn-th expand>Changes</vn-th>
<vn-th expand>After</vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
<vn-tr ng-repeat="log in $ctrl.logs"> <vn-tr ng-repeat="log in $ctrl.logs">
<vn-td shrink-datetime> <vn-td shrink-datetime>
{{::log.creationDate | date:'dd/MM/yyyy HH:mm'}} {{::log.creationDate | date:'dd/MM/yyyy HH:mm'}}
<div class="changes">
<div>
<span translate class="label">Changed by</span><span class="label">: </span>
<span ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
translate>{{::log.user.name || 'System' | translate}}
</span>
</div>
<div>
<span translate class="label">Model</span><span class="label">: </span>
<span translate class="value">{{::log.changedModel | dashIfEmpty}}</span>
</div>
<div>
<span translate class="label">Action</span><span class="label">: </span>
<span translate class="value">{{::$ctrl.actionsText[log.action] | dashIfEmpty}}</span>
</div>
<div>
<span translate class="label">Name</span><span class="label">: </span>
<span translate class="value">{{::log.changedModelValue | dashIfEmpty}}</span>
</div>
</div>
</vn-td> </vn-td>
<vn-td class="expendable"> <vn-td>
<span ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}" <span ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)" ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
translate>{{::log.user.name || 'System' | translate}} translate>{{::log.user.name || 'System' | translate}}
</span> </span>
</vn-td> </vn-td>
<vn-td class="expendable"> <vn-td ng-if="$ctrl.showModelName">
{{::log.changedModel}} {{::log.changedModel}}
</vn-td> </vn-td>
<vn-td translate class="expendable"> <vn-td shrink translate>
{{::$ctrl.actionsText[log.action]}} {{::$ctrl.actionsText[log.action]}}
</vn-td> </vn-td>
<vn-td class="expendable" expand> <vn-td ng-if="$ctrl.showModelName">
{{::log.changedModelValue}} {{::log.changedModelValue}}
</vn-td> </vn-td>
<vn-td expand class="before"> <vn-td expand>
<vn-one ng-repeat="old in log.oldProperties"> <table class="attributes">
<div> <thead>
<vn-label-value <tr>
no-ellipsize <th translate class="field">Field</th>
label="{{::old.key}}" <th translate>Before</th>
value="{{::old.value}}"> <th translate>After</th>
</vn-label-value> </tr>
</div> </thead>
</vn-one> <tbody>
</vn-td> <tr ng-repeat="prop in ::log.props">
<vn-td expand class="after"> <td class="field">{{prop.name}}</td>
<vn-one ng-repeat="new in log.newProperties" ng-if="!log.description" id="newInstance"> <td class="before">{{prop.old}}</td>
<div> <td class="after">{{prop.new}}</td>
<vn-label-value </tr>
no-ellipsize </tbody>
label="{{::new.key}}" </table>
value="{{::new.value}}"> <div ng-if="log.description != null">
</vn-label-value> {{::log.description}}
</div> </div>
</vn-one>
<vn-one ng-if="!log.newProperties" id="description">
<div>
<span no-ellipsize>{{::log.description}}</span>
</div>
</vn-one>
</vn-td> </vn-td>
</vn-tr> </vn-tr>
</vn-tbody> </vn-tbody>
@ -96,4 +70,4 @@
</vn-card> </vn-card>
</vn-data-viewer> </vn-data-viewer>
<vn-worker-descriptor-popover vn-id="workerDescriptor"> <vn-worker-descriptor-popover vn-id="workerDescriptor">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>

View File

@ -2,15 +2,17 @@ import ngModule from '../../module';
import Section from '../section'; import Section from '../section';
import './style.scss'; import './style.scss';
const validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
export default class Controller extends Section { export default class Controller extends Section {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this.actionsText = { this.actionsText = {
'insert': 'Creates', insert: 'Creates',
'update': 'Updates', update: 'Updates',
'delete': 'Deletes', delete: 'Deletes',
'select': 'Views' select: 'Views'
}; ``; };
this.filter = { this.filter = {
include: [{ include: [{
relation: 'user', relation: 'user',
@ -33,32 +35,57 @@ export default class Controller extends Section {
set logs(value) { set logs(value) {
this._logs = value; this._logs = value;
if (!value) return; if (!this.logs) return;
const empty = {};
const validations = window.validations; const validations = window.validations;
value.forEach(log => { for (const log of value) {
const locale = validations[log.changedModel] && validations[log.changedModel].locale ? validations[log.changedModel].locale : {}; const oldValues = log.oldInstance || empty;
const newValues = log.newInstance || empty;
const locale = validations[log.changedModel]?.locale || empty;
log.oldProperties = this.getInstance(log.oldInstance, locale); let props = Object.keys(oldValues).concat(Object.keys(newValues));
log.newProperties = this.getInstance(log.newInstance, locale); props = [...new Set(props)];
});
log.props = [];
for (const prop of props) {
log.props.push({
name: locale[prop] || prop,
old: this.formatValue(oldValues[prop]),
new: this.formatValue(newValues[prop])
});
}
}
} }
getInstance(instance, locale) { get showModelName() {
const properties = []; return !(this.changedModel && this.changedModelId);
let validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/; }
if (typeof instance == 'object' && instance != null) { formatValue(value) {
Object.keys(instance).forEach(property => { let type = typeof value;
if (validDate.test(instance[property]))
instance[property] = new Date(instance[property]).toLocaleString('es-ES');
const key = locale[property] || property; if (type === 'string' && validDate.test(value)) {
properties.push({key, value: instance[property]}); value = new Date(value);
}); type = typeof value;
return properties; }
switch (type) {
case 'boolean':
return value ? '✓' : '✗';
case 'object':
if (value instanceof Date) {
const hasZeroTime =
value.getHours() === 0 &&
value.getMinutes() === 0 &&
value.getSeconds() === 0;
const format = hasZeroTime ? 'dd/MM/yyyy' : 'dd/MM/yyyy HH:mm:ss';
return this.$filter('date')(value, format);
}
else
return value;
default:
return value;
} }
return null;
} }
showWorkerDescriptor(event, workerId) { showWorkerDescriptor(event, workerId) {
@ -73,6 +100,8 @@ ngModule.vnComponent('vnLog', {
bindings: { bindings: {
model: '<', model: '<',
originId: '<', originId: '<',
changedModel: '<?',
changedModelId: '<?',
url: '@' url: '@'
} }
}); });

View File

@ -11,4 +11,5 @@ Updates: Actualiza
Deletes: Elimina Deletes: Elimina
Views: Visualiza Views: Visualiza
System: Sistema System: Sistema
note: nota note: nota
Changes: Cambios

View File

@ -23,6 +23,28 @@ vn-log {
display: block; display: block;
} }
} }
.attributes {
width: 100%;
tr {
height: 10px;
& > td {
padding: 2px;
}
& > td.field,
& > th.field {
width: 20%;
color: gray;
}
& > td.before,
& > th.before,
& > td.after,
& > th.after {
width: 40%;
}
}
}
} }
.ellipsis { .ellipsis {
white-space: nowrap; white-space: nowrap;
@ -40,4 +62,4 @@ vn-log {
.alignSpan { .alignSpan {
overflow: hidden; overflow: hidden;
display: inline-block; display: inline-block;
} }

View File

@ -1,6 +1,27 @@
<div class="box"> <vn-textfield
<img src="./logo.svg"/> label="User"
<form name="form"> ng-model="$ctrl.user"
<ui-view></ui-view> vn-id="userField"
</form> vn-focus>
</vn-textfield>
<vn-textfield
label="Password"
ng-model="$ctrl.password"
type="password">
</vn-textfield>
<vn-check
label="Do not close session"
ng-model="$ctrl.remember"
name="remember">
</vn-check>
<div class="footer">
<vn-submit label="Enter" ng-click="$ctrl.submit()"></vn-submit>
<div class="spinner-wrapper">
<vn-spinner enable="$ctrl.loading"></vn-spinner>
</div>
<div class="vn-pt-lg">
<a ui-sref="recover-password" translate>
I do not remember my password
</a>
</div>
</div> </div>

View File

@ -1,16 +1,43 @@
import ngModule from '../../module'; import ngModule from '../../module';
import Component from 'core/lib/component';
import './style.scss'; import './style.scss';
export default class OutLayout extends Component { /**
constructor($element, $scope) { * A simple login form.
super($element, $scope); */
export default class Controller {
constructor($, $element, vnAuth) {
Object.assign(this, {
$,
$element,
vnAuth,
user: localStorage.getItem('lastUser'),
remember: true
});
}
submit() {
this.loading = true;
this.vnAuth.login(this.user, this.password, this.remember)
.then(() => {
localStorage.setItem('lastUser', this.user);
this.loading = false;
})
.catch(err => {
this.loading = false;
this.password = '';
this.focusUser();
throw err;
});
}
focusUser() {
this.$.userField.select();
this.$.userField.focus();
} }
} }
Controller.$inject = ['$scope', '$element', 'vnAuth'];
OutLayout.$inject = ['$element', '$scope']; ngModule.vnComponent('vnLogin', {
ngModule.vnComponent('vnOutLayout', {
template: require('./index.html'), template: require('./index.html'),
controller: OutLayout controller: Controller
}); });

View File

@ -1,16 +1,5 @@
User: Usuario User: Usuario
Password: Contraseña Password: Contraseña
Email: Correo electrónico
Do not close session: No cerrar sesión Do not close session: No cerrar sesión
Enter: Entrar Enter: Entrar
I do not remember my password: No recuerdo mi contraseña I do not remember my password: No recuerdo mi contraseña
Recover password: Recuperar contraseña
We will sent you an email to recover your password: Te enviaremos un correo para restablecer tu contraseña
Notification sent!: ¡Notificación enviada!
Reset password: Restrablecer contraseña
New password: Nueva contraseña
Repeat password: Repetir contraseña
Password requirements: >
La contraseña debe tener al menos {{ length }} caracteres de longitud,
{{nAlpha}} caracteres alfabéticos, {{nUpper}} letras mayúsculas, {{nDigits}}
dígitos y {{nPunct}} símbolos (Ej: $%&.)

View File

@ -1,27 +0,0 @@
<vn-textfield
label="User"
ng-model="$ctrl.user"
vn-id="userField"
vn-focus>
</vn-textfield>
<vn-textfield
label="Password"
ng-model="$ctrl.password"
type="password">
</vn-textfield>
<vn-check
label="Do not close session"
ng-model="$ctrl.remember"
name="remember">
</vn-check>
<div class="footer">
<vn-submit label="Enter" ng-click="$ctrl.submit()"></vn-submit>
<div class="spinner-wrapper">
<vn-spinner enable="$ctrl.loading"></vn-spinner>
</div>
<div class="vn-pt-lg">
<a ui-sref="recoverPassword" translate>
I do not remember my password
</a>
</div>
</div>

View File

@ -1,43 +0,0 @@
import ngModule from '../../module';
import './style.scss';
/**
* A simple login form.
*/
export default class Controller {
constructor($, $element, vnAuth) {
Object.assign(this, {
$,
$element,
vnAuth,
user: localStorage.getItem('lastUser'),
remember: true
});
}
submit() {
this.loading = true;
this.vnAuth.login(this.user, this.password, this.remember)
.then(() => {
localStorage.setItem('lastUser', this.user);
this.loading = false;
})
.catch(err => {
this.loading = false;
this.password = '';
this.focusUser();
throw err;
});
}
focusUser() {
this.$.userField.select();
this.$.userField.focus();
}
}
Controller.$inject = ['$scope', '$element', 'vnAuth'];
ngModule.vnComponent('vnLogin', {
template: require('./login.html'),
controller: Controller
});

View File

@ -1,8 +1,6 @@
@import "variables"; @import "variables";
vn-login, vn-login{
vn-reset-password,
vn-recover-password{
.footer { .footer {
margin-top: 32px; margin-top: 32px;
text-align: center; text-align: center;
@ -24,69 +22,3 @@ vn-recover-password{
} }
} }
} }
vn-out-layout{
position: absolute;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
color: $color-font;
font-size: 1.1rem;
font-weight: normal;
background-color: $color-bg-dark;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
& > .box {
box-sizing: border-box;
position: absolute;
max-width: 304px;
min-width: 240px;
padding: 48px;
background-color: $color-bg-panel;
box-shadow: 0 0 16px 0 rgba(0, 0, 0, .6);
border-radius: 8px;
& > img {
width: 100%;
padding-bottom: 16px;
}
& > form {
& > .vn-textfield {
width: 100%;
}
& > .vn-check {
display: block;
.md-label {
white-space: inherit;
}
}
}
h5{
color: $color-primary;
}
.text-secondary{
text-align: center;
padding-bottom: 16px;
}
}
@media screen and (max-width: 600px) {
background-color: $color-bg-panel;
& > .box {
padding: 16px;
box-shadow: none;
}
}
a{
color: $color-primary;
}
}

View File

@ -0,0 +1,6 @@
<div class="box">
<img src="./logo.svg"/>
<form name="form">
<ui-view></ui-view>
</form>
</div>

View File

@ -0,0 +1,16 @@
import ngModule from '../../module';
import Component from 'core/lib/component';
import './style.scss';
export default class OutLayout extends Component {
constructor($element, $scope) {
super($element, $scope);
}
}
OutLayout.$inject = ['$element', '$scope'];
ngModule.vnComponent('vnOutLayout', {
template: require('./index.html'),
controller: OutLayout
});

View File

@ -0,0 +1,67 @@
@import "variables";
vn-out-layout{
position: absolute;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
color: $color-font;
font-size: 1.1rem;
font-weight: normal;
background-color: $color-bg-dark;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
& > .box {
box-sizing: border-box;
position: absolute;
max-width: 304px;
min-width: 240px;
padding: 48px;
background-color: $color-bg-panel;
box-shadow: 0 0 16px 0 rgba(0, 0, 0, .6);
border-radius: 8px;
& > img {
width: 100%;
padding-bottom: 16px;
}
& > form {
& > .vn-textfield {
width: 100%;
}
& > .vn-check {
display: block;
.md-label {
white-space: inherit;
}
}
}
h5{
color: $color-primary;
}
.text-secondary{
text-align: center;
padding-bottom: 16px;
}
}
@media screen and (max-width: 600px) {
background-color: $color-bg-panel;
& > .box {
padding: 16px;
box-shadow: none;
}
}
a{
color: $color-primary;
}
}

View File

@ -32,6 +32,6 @@ export default class Controller {
Controller.$inject = ['$scope', '$element', '$http', 'vnApp', '$translate', '$state']; Controller.$inject = ['$scope', '$element', '$http', 'vnApp', '$translate', '$state'];
ngModule.vnComponent('vnRecoverPassword', { ngModule.vnComponent('vnRecoverPassword', {
template: require('./recover-password.html'), template: require('./index.html'),
controller: Controller controller: Controller
}); });

View File

@ -0,0 +1,3 @@
Recover password: Recuperar contraseña
We will sent you an email to recover your password: Te enviaremos un correo para restablecer tu contraseña
Notification sent!: ¡Notificación enviada!

View File

@ -0,0 +1,24 @@
@import "variables";
vn-recover-password{
.footer {
margin-top: 32px;
text-align: center;
position: relative;
& > .vn-submit {
display: block;
& > input {
display: block;
width: 100%;
}
}
& > .spinner-wrapper {
position: absolute;
width: 0;
top: 3px;
right: -8px;
overflow: visible;
}
}
}

View File

@ -43,6 +43,6 @@ export default class Controller {
Controller.$inject = ['$scope', '$element', '$http', 'vnApp', '$translate', '$state', '$location']; Controller.$inject = ['$scope', '$element', '$http', 'vnApp', '$translate', '$state', '$location'];
ngModule.vnComponent('vnResetPassword', { ngModule.vnComponent('vnResetPassword', {
template: require('./reset-password.html'), template: require('./index.html'),
controller: Controller controller: Controller
}); });

View File

@ -1,7 +1,3 @@
User: User
Password: Password
Do not close session: Do not close session
Enter: Enter
Password requirements: > Password requirements: >
The password must have at least {{ length }} length characters, The password must have at least {{ length }} length characters,
{{nAlpha}} alphabetic characters, {{nUpper}} capital letters, {{nDigits}} {{nAlpha}} alphabetic characters, {{nUpper}} capital letters, {{nDigits}}

View File

@ -0,0 +1,8 @@
Reset password: Restrablecer contraseña
New password: Nueva contraseña
Repeat password: Repetir contraseñaç
Password changed!: ¡Contraseña cambiada!
Password requirements: >
La contraseña debe tener al menos {{ length }} caracteres de longitud,
{{nAlpha}} caracteres alfabéticos, {{nUpper}} letras mayúsculas, {{nDigits}}
dígitos y {{nPunct}} símbolos (Ej: $%&.)

View File

@ -0,0 +1,24 @@
@import "variables";
vn-reset-password{
.footer {
margin-top: 32px;
text-align: center;
position: relative;
& > .vn-submit {
display: block;
& > input {
display: block;
width: 100%;
}
}
& > .spinner-wrapper {
position: absolute;
width: 0;
top: 3px;
right: -8px;
overflow: visible;
}
}
}

View File

@ -1,19 +1,26 @@
import ngModule from '../module'; import ngModule from '../../module';
import Component from 'core/lib/component';
import './style.scss'; import './style.scss';
import Dialog from '../../../core/components/dialog';
export default class sendSmsDialog extends Dialog {
constructor($element, $scope, $http, $translate, vnApp) {
super($element, $scope, $http, $translate, vnApp);
new CustomEvent('openSmsDialog', {
detail: {
this: this
}
});
}
class Controller extends Component {
open() { open() {
this.$.SMSDialog.show(); this.$.SMSDialog.show();
} }
charactersRemaining() { charactersRemaining() {
const element = this.$.message; const element = this.sms.message;
const value = element.input.value;
const maxLength = 160; const maxLength = 160;
const textAreaLength = new Blob([value]).size; return maxLength - element.length;
return maxLength - textAreaLength;
} }
onResponse() { onResponse() {
@ -25,23 +32,19 @@ class Controller extends Component {
if (this.charactersRemaining() < 0) if (this.charactersRemaining() < 0)
throw new Error(`The message it's too long`); throw new Error(`The message it's too long`);
this.$http.post(`Tickets/${this.sms.ticketId}/sendSms`, this.sms).then(res => { return this.onSend({$sms: this.sms});
this.vnApp.showMessage(this.$t('SMS sent!'));
if (res.data) this.emit('send', {response: res.data});
});
} catch (e) { } catch (e) {
this.vnApp.showError(this.$t(e.message)); this.vnApp.showError(this.$t(e.message));
return false; return false;
} }
return true;
} }
} }
ngModule.vnComponent('vnTicketSms', { ngModule.vnComponent('vnSmsDialog', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller, controller: sendSmsDialog,
bindings: { bindings: {
sms: '<', sms: '<',
onSend: '&',
} }
}); });

View File

@ -3,25 +3,38 @@ import getMainRoute from 'core/lib/get-main-route';
config.$inject = ['$stateProvider', '$urlRouterProvider']; config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) { function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/'); $urlRouterProvider
.otherwise('/');
$stateProvider $stateProvider
.state('layout', {
abstract: true,
template: '<vn-layout></vn-layout>',
})
.state('outLayout', {
abstract: true,
template: '<vn-out-layout></vn-out-layout>',
})
.state('login', { .state('login', {
parent: 'outLayout',
url: '/login?continue', url: '/login?continue',
description: 'Login', description: 'Login',
template: '<vn-login></vn-login>' template: '<vn-login></vn-login>'
}) })
.state('recoverPassword', { .state('recover-password', {
parent: 'outLayout',
url: '/recover-password', url: '/recover-password',
description: 'Recover-password', description: 'Recover password',
template: '<vn-recover-password>asd</vn-recover-password>' template: '<vn-recover-password></vn-recover-password>'
}) })
.state('resetPassword', { .state('reset-password', {
parent: 'outLayout',
url: '/reset-password', url: '/reset-password',
description: 'Reset-password', description: 'Reset password',
template: '<vn-reset-password></vn-reset-password>' template: '<vn-reset-password></vn-reset-password>'
}) })
.state('home', { .state('home', {
parent: 'layout',
url: '/', url: '/',
description: 'Home', description: 'Home',
template: '<vn-home></vn-home>' template: '<vn-home></vn-home>'
@ -52,6 +65,10 @@ function config($stateProvider, $urlRouterProvider) {
}; };
if (route.abstract) if (route.abstract)
configRoute.abstract = true; configRoute.abstract = true;
if (!route.state.includes('.'))
configRoute.parent = 'layout';
if (route.routeParams) if (route.routeParams)
configRoute.params = route.routeParams; configRoute.params = route.routeParams;

View File

@ -66,7 +66,8 @@
"MESSAGE_INSURANCE_CHANGE": "I have changed the insurence credit of client [{{clientName}} ({{clientId}})]({{{url}}}) to *{{credit}} €*", "MESSAGE_INSURANCE_CHANGE": "I have changed the insurence credit of client [{{clientName}} ({{clientId}})]({{{url}}}) to *{{credit}} €*",
"Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})", "Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})",
"Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})", "Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})",
"Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", "Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}",
"Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked",
"Claim state has changed to incomplete": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *incomplete*", "Claim state has changed to incomplete": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *incomplete*",
"Claim state has changed to canceled": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *canceled*", "Claim state has changed to canceled": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *canceled*",
"Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member",
@ -136,12 +137,14 @@
"Password does not meet requirements": "Password does not meet requirements", "Password does not meet requirements": "Password does not meet requirements",
"You don't have privileges to change the zone": "You don't have privileges to change the zone or for these parameters there are more than one shipping options, talk to agencies", "You don't have privileges to change the zone": "You don't have privileges to change the zone or for these parameters there are more than one shipping options, talk to agencies",
"Not enough privileges to edit a client": "Not enough privileges to edit a client", "Not enough privileges to edit a client": "Not enough privileges to edit a client",
"Claim pickup order sent": "Claim pickup order sent [({{claimId}})]({{{claimUrl}}}) to client *{{clientName}}*", "Claim pickup order sent": "Claim pickup order sent [{{claimId}}]({{{claimUrl}}}) to client *{{clientName}}*",
"You don't have grant privilege": "You don't have grant privilege", "You don't have grant privilege": "You don't have grant privilege",
"You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user", "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user",
"Email verify": "Email verify", "Email verify": "Email verify",
"Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) merged with [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})", "Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) merged with [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
"Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production", "Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production",
"App locked": "App locked by user {{userId}}",
"The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified",
"Receipt's bank was not found": "Receipt's bank was not found", "Receipt's bank was not found": "Receipt's bank was not found",
"This receipt was not compensated": "This receipt was not compensated", "This receipt was not compensated": "This receipt was not compensated",
"Client's email was not found": "Client's email was not found" "Client's email was not found": "Client's email was not found"

View File

@ -134,7 +134,8 @@
"MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} ({{clientId}})]({{{url}}}) a *{{credit}} €*", "MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} ({{clientId}})]({{{url}}}) a *{{credit}} €*",
"Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})", "Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})", "Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
"Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*", "Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}",
"Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*",
"Claim state has changed to incomplete": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *incompleta*", "Claim state has changed to incomplete": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *incompleta*",
"Claim state has changed to canceled": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *anulado*", "Claim state has changed to canceled": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *anulado*",
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}", "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
@ -238,18 +239,20 @@
"Modifiable password only via recovery or by an administrator": "Contraseña modificable solo a través de la recuperación o por un administrador", "Modifiable password only via recovery or by an administrator": "Contraseña modificable solo a través de la recuperación o por un administrador",
"Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente", "Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente",
"This route does not exists": "Esta ruta no existe", "This route does not exists": "Esta ruta no existe",
"Claim pickup order sent": "Reclamación Orden de recogida enviada [({{claimId}})]({{{claimUrl}}}) al cliente *{{clientName}}*", "Claim pickup order sent": "Reclamación Orden de recogida enviada [{{claimId}}]({{{claimUrl}}}) al cliente *{{clientName}}*",
"You don't have grant privilege": "No tienes privilegios para dar privilegios", "You don't have grant privilege": "No tienes privilegios para dar privilegios",
"You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario", "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario",
"Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) fusionado con [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})", "Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) fusionado con [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
"Already has this status": "Ya tiene este estado", "Already has this status": "Ya tiene este estado",
"There aren't records for this week": "No existen registros para esta semana", "There aren't records for this week": "No existen registros para esta semana",
"Empty data source": "Origen de datos vacio", "Empty data source": "Origen de datos vacio",
"App locked": "Aplicación bloqueada por el usuario {{userId}}",
"Email verify": "Correo de verificación", "Email verify": "Correo de verificación",
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment", "Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
"Receipt's bank was not found": "No se encontró el banco del recibo", "Receipt's bank was not found": "No se encontró el banco del recibo",
"This receipt was not compensated": "Este recibo no ha sido compensado", "This receipt was not compensated": "Este recibo no ha sido compensado",
"Client's email was not found": "No se encontró el email del cliente", "Client's email was not found": "No se encontró el email del cliente",
"App name does not exist": "El nombre de aplicación no es válido", "App name does not exist": "El nombre de aplicación no es válido",
"Try again": "Vuelve a intentarlo" "Try again": "Vuelve a intentarlo",
"Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9"
} }

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