Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2752-entry_import_buys
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Joan Sanchez 2021-03-04 07:54:15 +01:00
commit 0b532880c0
175 changed files with 12083 additions and 34165 deletions

View File

@ -35,3 +35,4 @@ rules:
space-in-parens: ["error", "never"] space-in-parens: ["error", "never"]
jasmine/no-focused-tests: 0 jasmine/no-focused-tests: 0
jasmine/prefer-toHaveBeenCalledWith: 0 jasmine/prefer-toHaveBeenCalledWith: 0
arrow-spacing: ["error", { "before": true, "after": true }]

View File

@ -38,8 +38,7 @@ module.exports = Self => {
{ {
arg: 'hasFile', arg: 'hasFile',
type: 'Boolean', type: 'Boolean',
description: 'True if has an attached file', description: 'True if has an attached file'
required: true
}, },
{ {
arg: 'hasFileAttached', arg: 'hasFileAttached',

View File

@ -110,11 +110,10 @@ module.exports = Self => {
async function createDms(ctx, file, myOptions) { async function createDms(ctx, file, myOptions) {
const models = Self.app.models; const models = Self.app.models;
const myUserId = ctx.req.accessToken.userId; const myUserId = ctx.req.accessToken.userId;
const myWorker = await models.Worker.findOne({where: {userFk: myUserId}}, myOptions);
const args = ctx.args; const args = ctx.args;
const newDms = await Self.create({ const newDms = await Self.create({
workerFk: myWorker.id, workerFk: myUserId,
dmsTypeFk: args.dmsTypeId, dmsTypeFk: args.dmsTypeId,
companyFk: args.companyId, companyFk: args.companyId,
warehouseFk: args.warehouseId, warehouseFk: args.warehouseId,

View File

@ -0,0 +1,28 @@
module.exports = function(Self) {
Self.remoteMethodCtx('getStarredModules', {
description: 'returns the starred modules for the current user',
accessType: 'READ',
returns: {
type: 'object',
root: true
},
http: {
path: `/getStarredModules`,
verb: 'get'
}
});
Self.getStarredModules = async ctx => {
const userId = ctx.req.accessToken.userId;
const filter = {
where: {
workerFk: userId
},
fields: ['moduleFk']
};
const starredModules = await Self.app.models.StarredModule.find(filter);
return starredModules;
};
};

View File

@ -0,0 +1,31 @@
const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');
describe('getStarredModules()', () => {
const activeCtx = {
accessToken: {userId: 9},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
const ctx = {req: activeCtx};
beforeEach(() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
});
it(`should return the starred modules for a given user`, async() => {
const newStarred = await app.models.StarredModule.create({workerFk: 9, moduleFk: 'Clients'});
const starredModules = await app.models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1);
expect(starredModules[0].moduleFk).toEqual('Clients');
// restores
await app.models.StarredModule.destroyById(newStarred.id);
});
});

View File

@ -0,0 +1,36 @@
const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');
describe('toggleStarredModule()', () => {
const activeCtx = {
accessToken: {userId: 9},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
const ctx = {
req: activeCtx
};
beforeEach(() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
});
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');
let starredModules = await app.models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(1);
expect(starredModule.moduleFk).toEqual('Orders');
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders');
starredModules = await app.models.StarredModule.getStarredModules(ctx);
expect(starredModules.length).toEqual(0);
});
});

View File

@ -0,0 +1,41 @@
module.exports = function(Self) {
Self.remoteMethodCtx('toggleStarredModule', {
description: 'creates or deletes a starred module for the current user',
accessType: 'WRITE',
returns: {
type: 'object',
root: true
},
accepts: {
arg: 'moduleName',
type: 'string',
required: true,
description: 'The module name'
},
http: {
path: `/toggleStarredModule`,
verb: 'post'
}
});
Self.toggleStarredModule = async(ctx, moduleName) => {
const userId = ctx.req.accessToken.userId;
const filter = {
where: {
workerFk: userId,
moduleFk: moduleName
}
};
const [starredModule] = await Self.app.models.StarredModule.find(filter);
if (starredModule)
await starredModule.destroy();
else {
return Self.app.models.StarredModule.create({
workerFk: userId,
moduleFk: moduleName
});
}
};
};

View File

@ -59,6 +59,9 @@
"Language": { "Language": {
"dataSource": "vn" "dataSource": "vn"
}, },
"Module": {
"dataSource": "vn"
},
"Province": { "Province": {
"dataSource": "vn" "dataSource": "vn"
}, },
@ -71,6 +74,9 @@
"SageWithholding": { "SageWithholding": {
"dataSource": "vn" "dataSource": "vn"
}, },
"StarredModule": {
"dataSource": "vn"
},
"TempContainer": { "TempContainer": {
"dataSource": "tempStorage" "dataSource": "tempStorage"
}, },

View File

@ -0,0 +1,13 @@
module.exports = Self => {
Self.validatesPresenceOf('name', {
message: 'Name cannot be blank'
});
Self.validatesPresenceOf('bic', {
message: 'Swift / BIC cannot be empty'
});
Self.validatesUniquenessOf('bic', {
message: 'This BIC already exist.'
});
};

View File

@ -1,11 +1,51 @@
const fs = require('fs-extra'); const fs = require('fs-extra');
const sharp = require('sharp'); const sharp = require('sharp');
const path = require('path'); const path = require('path');
const readChunk = require('read-chunk');
const imageType = require('image-type');
const bmp = require('bmp-js');
module.exports = Self => { module.exports = Self => {
require('../methods/image/download')(Self); require('../methods/image/download')(Self);
require('../methods/image/upload')(Self); require('../methods/image/upload')(Self);
// Function extracted from jimp package (utils)
function scan(image, x, y, w, h, f) {
// round input
x = Math.round(x);
y = Math.round(y);
w = Math.round(w);
h = Math.round(h);
for (let _y = y; _y < y + h; _y++) {
for (let _x = x; _x < x + w; _x++) {
const idx = (image.bitmap.width * _y + _x) << 2;
f.call(image, _x, _y, idx);
}
}
return image;
}
// Function extracted from jimp package (type-bmp)
function fromAGBR(bitmap) {
return scan({bitmap}, 0, 0, bitmap.width, bitmap.height, function(
x,
y,
index
) {
const alpha = this.bitmap.data[index + 0];
const blue = this.bitmap.data[index + 1];
const green = this.bitmap.data[index + 2];
const red = this.bitmap.data[index + 3];
this.bitmap.data[index + 0] = red;
this.bitmap.data[index + 1] = green;
this.bitmap.data[index + 2] = blue;
this.bitmap.data[index + 3] = bitmap.is_with_alpha ? alpha : 0xff;
}).bitmap;
}
Self.registerImage = async(collectionName, srcFilePath, fileName, entityId) => { Self.registerImage = async(collectionName, srcFilePath, fileName, entityId) => {
const models = Self.app.models; const models = Self.app.models;
const tx = await Self.beginTransaction({}); const tx = await Self.beginTransaction({});
@ -48,13 +88,31 @@ module.exports = Self => {
const dstDir = path.join(collectionDir, 'full'); const dstDir = path.join(collectionDir, 'full');
const dstFile = path.join(dstDir, file); const dstFile = path.join(dstDir, file);
const buffer = readChunk.sync(srcFilePath, 0, 12);
const type = imageType(buffer);
let sharpOptions;
let imgSrc = srcFilePath;
if (type.mime == 'image/bmp') {
const bmpBuffer = fs.readFileSync(srcFilePath);
const bmpData = fromAGBR(bmp.decode(bmpBuffer));
imgSrc = bmpData.data;
sharpOptions = {
raw: {
width: bmpData.width,
height: bmpData.height,
channels: 4
}
};
}
const resizeOpts = { const resizeOpts = {
withoutEnlargement: true, withoutEnlargement: true,
fit: 'inside' fit: 'inside'
}; };
await fs.mkdir(dstDir, {recursive: true}); await fs.mkdir(dstDir, {recursive: true});
await sharp(srcFilePath, {failOnError: false}) await sharp(imgSrc, sharpOptions)
.resize(collection.maxWidth, collection.maxHeight, resizeOpts) .resize(collection.maxWidth, collection.maxHeight, resizeOpts)
.png() .png()
.toFile(dstFile); .toFile(dstFile);
@ -69,7 +127,7 @@ module.exports = Self => {
}; };
await fs.mkdir(dstDir, {recursive: true}); await fs.mkdir(dstDir, {recursive: true});
await sharp(srcFilePath, {failOnError: false}) await sharp(imgSrc, sharpOptions)
.resize(size.width, size.height, resizeOpts) .resize(size.width, size.height, resizeOpts)
.png() .png()
.toFile(dstFile); .toFile(dstFile);

23
back/models/module.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "Module",
"base": "VnModel",
"options": {
"mysql": {
"table": "salix.module"
}
},
"properties": {
"code": {
"type": "string",
"id": true
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -0,0 +1,4 @@
module.exports = Self => {
require('../methods/starred-module/getStarredModules')(Self);
require('../methods/starred-module/toggleStarredModule')(Self);
};

View File

@ -0,0 +1,35 @@
{
"name": "StarredModule",
"base": "VnModel",
"options": {
"mysql": {
"table": "vn.starredModule"
}
},
"properties": {
"id": {
"type": "number",
"id": true
},
"workerFk": {
"type": "number",
"required": true
},
"moduleFk": {
"type": "string",
"required": true
}
},
"relations": {
"worker": {
"type": "belongsTo",
"model": "Worker",
"foreignKey": "workerFk"
},
"module": {
"type": "belongsTo",
"model": "Module",
"foreignKey": "moduleFk"
}
}
}

View File

@ -1,8 +0,0 @@
UPDATE `salix`.`ACL` SET `principalId` = 'deliveryBoss' WHERE (`id` = '194');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '97');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '100');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '103');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '202');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Town', '*', 'WRITE', 'ALLOW', 'ROLE', 'deliveryBoss');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Province', '*', 'WRITE', 'ALLOW', 'ROLE', 'deliveryBoss');

View File

@ -1,3 +0,0 @@
UPDATE `vn`.`claimState` SET `roleFk` = '72' WHERE (`id` = '3');
UPDATE `vn`.`claimState` SET `roleFk` = '72' WHERE (`id` = '4');
UPDATE `vn`.`claimState` SET `roleFk` = '72' WHERE (`id` = '5');

View File

@ -1,9 +0,0 @@
ALTER TABLE `vn`.`observationType`
ADD COLUMN `code` VARCHAR(45) NOT NULL AFTER `description`;
UPDATE `vn`.`observationType` SET `code` = 'itemPicker' WHERE (`id` = '1');
UPDATE `vn`.`observationType` SET `code` = 'packager' WHERE (`id` = '2');
UPDATE `vn`.`observationType` SET `code` = 'salesPerson' WHERE (`id` = '4');
UPDATE `vn`.`observationType` SET `code` = 'administrative' WHERE (`id` = '5');
UPDATE `vn`.`observationType` SET `code` = 'weight' WHERE (`id` = '6');
UPDATE `vn`.`observationType` SET `code` = 'delivery' WHERE (`id` = '3');

View File

@ -1,7 +0,0 @@
ALTER TABLE `account`.`roleRole`
ADD `id` INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
UPDATE `account`.`role` SET id = 100 WHERE `name` = 'root';
CALL account.role_sync;

View File

@ -1,504 +0,0 @@
DROP PROCEDURE IF EXISTS account.role_syncPrivileges;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `account`.`role_syncPrivileges`()
BEGIN
/**
* Synchronizes permissions of MySQL role users based on role hierarchy.
* The computed role users of permission mix will be named according to
* pattern z-[role_name].
*
* If any@localhost user exists, it will be taken as a template for basic
* attributes.
*
* Warning! This procedure should only be called when MySQL privileges
* are modified. If role hierarchy is modified, you must call the role_sync()
* procedure wich calls this internally.
*/
DECLARE vIsMysql BOOL DEFAULT VERSION() NOT LIKE '%MariaDB%';
DECLARE vVersion INT DEFAULT SUBSTRING_INDEX(VERSION(), '.', 1);
DECLARE vTplUser VARCHAR(255) DEFAULT 'any';
DECLARE vTplHost VARCHAR(255) DEFAULT '%';
DECLARE vRoleHost VARCHAR(255) DEFAULT 'localhost';
DECLARE vAllHost VARCHAR(255) DEFAULT '%';
DECLARE vPrefix VARCHAR(2) DEFAULT 'z-';
DECLARE vPrefixedLike VARCHAR(255);
DECLARE vPassword VARCHAR(255) DEFAULT '';
-- Deletes computed role users
SET vPrefixedLike = CONCAT(vPrefix, '%');
IF vIsMysql THEN
DELETE FROM mysql.user
WHERE `User` LIKE vPrefixedLike;
ELSE
DELETE FROM mysql.global_priv
WHERE `User` LIKE vPrefixedLike;
END IF;
DELETE FROM mysql.db
WHERE `User` LIKE vPrefixedLike;
DELETE FROM mysql.tables_priv
WHERE `User` LIKE vPrefixedLike;
DELETE FROM mysql.columns_priv
WHERE `User` LIKE vPrefixedLike;
DELETE FROM mysql.procs_priv
WHERE `User` LIKE vPrefixedLike;
DELETE FROM mysql.proxies_priv
WHERE `Proxied_user` LIKE vPrefixedLike;
-- Temporary tables
DROP TEMPORARY TABLE IF EXISTS tRole;
CREATE TEMPORARY TABLE tRole
(INDEX (id))
ENGINE = MEMORY
SELECT
id,
`name` role,
CONCAT(vPrefix, `name`) prefixedRole
FROM role
WHERE hasLogin;
DROP TEMPORARY TABLE IF EXISTS tRoleInherit;
CREATE TEMPORARY TABLE tRoleInherit
(INDEX (inheritsFrom))
ENGINE = MEMORY
SELECT
r.prefixedRole,
ri.`name` inheritsFrom
FROM tRole r
JOIN roleRole rr ON rr.role = r.id
JOIN role ri ON ri.id = rr.inheritsFrom;
-- Recreate role users
IF vIsMysql THEN
DROP TEMPORARY TABLE IF EXISTS tUser;
CREATE TEMPORARY TABLE tUser
SELECT
r.prefixedRole `User`,
vTplHost `Host`,
IFNULL(t.`authentication_string`,
'') `authentication_string`,
IFNULL(t.`plugin`,
'mysql_native_password') `plugin`,
IFNULL(IF('' != u.`ssl_type`,
u.`ssl_type`, t.`ssl_type`),
'') `ssl_type`,
IFNULL(IF('' != u.`ssl_cipher`,
u.`ssl_cipher`, t.`ssl_cipher`),
'') `ssl_cipher`,
IFNULL(IF('' != u.`x509_issuer`,
u.`x509_issuer`, t.`x509_issuer`),
'') `x509_issuer`,
IFNULL(IF('' != u.`x509_subject`,
u.`x509_subject`, t.`x509_subject`),
'') `x509_subject`,
IFNULL(IF(0 != u.`max_questions`,
u.`max_questions`, t.`max_questions`),
0) `max_questions`,
IFNULL(IF(0 != u.`max_updates`,
u.`max_updates`, t.`max_updates`),
0) `max_updates`,
IFNULL(IF(0 != u.`max_connections`,
u.`max_connections`, t.`max_connections`),
0) `max_connections`,
IFNULL(IF(0 != u.`max_user_connections`,
u.`max_user_connections`, t.`max_user_connections`),
0) `max_user_connections`
FROM tRole r
LEFT JOIN mysql.user t
ON t.`User` = vTplUser
AND t.`Host` = vRoleHost
LEFT JOIN mysql.user u
ON u.`User` = r.role
AND u.`Host` = vRoleHost;
IF vVersion <= 5 THEN
SELECT `Password` INTO vPassword
FROM mysql.user
WHERE `User` = vTplUser
AND `Host` = vRoleHost;
INSERT INTO mysql.user (
`User`,
`Host`,
`Password`,
`authentication_string`,
`plugin`,
`ssl_type`,
`ssl_cipher`,
`x509_issuer`,
`x509_subject`,
`max_questions`,
`max_updates`,
`max_connections`,
`max_user_connections`
)
SELECT
`User`,
`Host`,
vPassword,
`authentication_string`,
`plugin`,
`ssl_type`,
`ssl_cipher`,
`x509_issuer`,
`x509_subject`,
`max_questions`,
`max_updates`,
`max_connections`,
`max_user_connections`
FROM tUser;
ELSE
INSERT INTO mysql.user (
`User`,
`Host`,
`authentication_string`,
`plugin`,
`ssl_type`,
`ssl_cipher`,
`x509_issuer`,
`x509_subject`,
`max_questions`,
`max_updates`,
`max_connections`,
`max_user_connections`
)
SELECT
`User`,
`Host`,
`authentication_string`,
`plugin`,
`ssl_type`,
`ssl_cipher`,
`x509_issuer`,
`x509_subject`,
`max_questions`,
`max_updates`,
`max_connections`,
`max_user_connections`
FROM tUser;
END IF;
DROP TEMPORARY TABLE IF EXISTS tUser;
ELSE
INSERT INTO mysql.global_priv (
`User`,
`Host`,
`Priv`
)
SELECT
r.prefixedRole,
vTplHost,
JSON_MERGE_PATCH(
IFNULL(t.`Priv`, '{}'),
IFNULL(u.`Priv`, '{}'),
JSON_OBJECT(
'mysql_old_password', JSON_VALUE(t.`Priv`, '$.mysql_old_password'),
'mysql_native_password', JSON_VALUE(t.`Priv`, '$.mysql_native_password'),
'authentication_string', JSON_VALUE(t.`Priv`, '$.authentication_string'),
'ssl_type', JSON_VALUE(t.`Priv`, '$.ssl_type')
)
)
FROM tRole r
LEFT JOIN mysql.global_priv t
ON t.`User` = vTplUser
AND t.`Host` = vRoleHost
LEFT JOIN mysql.global_priv u
ON u.`User` = r.role
AND u.`Host` = vRoleHost;
END IF;
INSERT INTO mysql.proxies_priv (
`User`,
`Host`,
`Proxied_user`,
`Proxied_host`,
`Grantor`
)
SELECT
'',
vAllHost,
prefixedRole,
vTplHost,
CONCAT(prefixedRole, '@', vTplHost)
FROM tRole;
-- Copies global privileges
DROP TEMPORARY TABLE IF EXISTS tUserPriv;
IF vIsMysql THEN
CREATE TEMPORARY TABLE tUserPriv
(INDEX (prefixedRole))
ENGINE = MEMORY
SELECT
r.prefixedRole,
MAX(u.`Select_priv`) `Select_priv`,
MAX(u.`Insert_priv`) `Insert_priv`,
MAX(u.`Update_priv`) `Update_priv`,
MAX(u.`Delete_priv`) `Delete_priv`,
MAX(u.`Create_priv`) `Create_priv`,
MAX(u.`Drop_priv`) `Drop_priv`,
MAX(u.`Reload_priv`) `Reload_priv`,
MAX(u.`Shutdown_priv`) `Shutdown_priv`,
MAX(u.`Process_priv`) `Process_priv`,
MAX(u.`File_priv`) `File_priv`,
MAX(u.`Grant_priv`) `Grant_priv`,
MAX(u.`References_priv`) `References_priv`,
MAX(u.`Index_priv`) `Index_priv`,
MAX(u.`Alter_priv`) `Alter_priv`,
MAX(u.`Show_db_priv`) `Show_db_priv`,
MAX(u.`Super_priv`) `Super_priv`,
MAX(u.`Create_tmp_table_priv`) `Create_tmp_table_priv`,
MAX(u.`Lock_tables_priv`) `Lock_tables_priv`,
MAX(u.`Execute_priv`) `Execute_priv`,
MAX(u.`Repl_slave_priv`) `Repl_slave_priv`,
MAX(u.`Repl_client_priv`) `Repl_client_priv`,
MAX(u.`Create_view_priv`) `Create_view_priv`,
MAX(u.`Show_view_priv`) `Show_view_priv`,
MAX(u.`Create_routine_priv`) `Create_routine_priv`,
MAX(u.`Alter_routine_priv`) `Alter_routine_priv`,
MAX(u.`Create_user_priv`) `Create_user_priv`,
MAX(u.`Event_priv`) `Event_priv`,
MAX(u.`Trigger_priv`) `Trigger_priv`,
MAX(u.`Create_tablespace_priv`) `Create_tablespace_priv`
FROM tRoleInherit r
JOIN mysql.user u
ON u.`User` = r.inheritsFrom
AND u.`Host`= vRoleHost
GROUP BY r.prefixedRole;
UPDATE mysql.user u
JOIN tUserPriv t
ON u.`User` = t.prefixedRole
AND u.`Host` = vTplHost
SET
u.`Select_priv`
= t.`Select_priv`,
u.`Insert_priv`
= t.`Insert_priv`,
u.`Update_priv`
= t.`Update_priv`,
u.`Delete_priv`
= t.`Delete_priv`,
u.`Create_priv`
= t.`Create_priv`,
u.`Drop_priv`
= t.`Drop_priv`,
u.`Reload_priv`
= t.`Reload_priv`,
u.`Shutdown_priv`
= t.`Shutdown_priv`,
u.`Process_priv`
= t.`Process_priv`,
u.`File_priv`
= t.`File_priv`,
u.`Grant_priv`
= t.`Grant_priv`,
u.`References_priv`
= t.`References_priv`,
u.`Index_priv`
= t.`Index_priv`,
u.`Alter_priv`
= t.`Alter_priv`,
u.`Show_db_priv`
= t.`Show_db_priv`,
u.`Super_priv`
= t.`Super_priv`,
u.`Create_tmp_table_priv`
= t.`Create_tmp_table_priv`,
u.`Lock_tables_priv`
= t.`Lock_tables_priv`,
u.`Execute_priv`
= t.`Execute_priv`,
u.`Repl_slave_priv`
= t.`Repl_slave_priv`,
u.`Repl_client_priv`
= t.`Repl_client_priv`,
u.`Create_view_priv`
= t.`Create_view_priv`,
u.`Show_view_priv`
= t.`Show_view_priv`,
u.`Create_routine_priv`
= t.`Create_routine_priv`,
u.`Alter_routine_priv`
= t.`Alter_routine_priv`,
u.`Create_user_priv`
= t.`Create_user_priv`,
u.`Event_priv`
= t.`Event_priv`,
u.`Trigger_priv`
= t.`Trigger_priv`,
u.`Create_tablespace_priv`
= t.`Create_tablespace_priv`;
ELSE
CREATE TEMPORARY TABLE tUserPriv
(INDEX (prefixedRole))
SELECT
r.prefixedRole,
BIT_OR(JSON_VALUE(p.`Priv`, '$.access')) access
FROM tRoleInherit r
JOIN mysql.global_priv p
ON p.`User` = r.inheritsFrom
AND p.`Host`= vRoleHost
GROUP BY r.prefixedRole;
UPDATE mysql.global_priv p
JOIN tUserPriv t
ON p.`User` = t.prefixedRole
AND p.`Host` = vTplHost
SET
p.`Priv` = JSON_SET(p.`Priv`, '$.access', t.access);
END IF;
DROP TEMPORARY TABLE tUserPriv;
-- Copy schema level privileges
INSERT INTO mysql.db (
`User`,
`Host`,
`Db`,
`Select_priv`,
`Insert_priv`,
`Update_priv`,
`Delete_priv`,
`Create_priv`,
`Drop_priv`,
`Grant_priv`,
`References_priv`,
`Index_priv`,
`Alter_priv`,
`Create_tmp_table_priv`,
`Lock_tables_priv`,
`Create_view_priv`,
`Show_view_priv`,
`Create_routine_priv`,
`Alter_routine_priv`,
`Execute_priv`,
`Event_priv`,
`Trigger_priv`
)
SELECT
r.prefixedRole,
vTplHost,
t.`Db`,
MAX(t.`Select_priv`),
MAX(t.`Insert_priv`),
MAX(t.`Update_priv`),
MAX(t.`Delete_priv`),
MAX(t.`Create_priv`),
MAX(t.`Drop_priv`),
MAX(t.`Grant_priv`),
MAX(t.`References_priv`),
MAX(t.`Index_priv`),
MAX(t.`Alter_priv`),
MAX(t.`Create_tmp_table_priv`),
MAX(t.`Lock_tables_priv`),
MAX(t.`Create_view_priv`),
MAX(t.`Show_view_priv`),
MAX(t.`Create_routine_priv`),
MAX(t.`Alter_routine_priv`),
MAX(t.`Execute_priv`),
MAX(t.`Event_priv`),
MAX(t.`Trigger_priv`)
FROM tRoleInherit r
JOIN mysql.db t
ON t.`User` = r.inheritsFrom
AND t.`Host`= vRoleHost
GROUP BY r.prefixedRole, t.`Db`;
-- Copy table level privileges
INSERT INTO mysql.tables_priv (
`User`,
`Host`,
`Db`,
`Table_name`,
`Grantor`,
`Timestamp`,
`Table_priv`,
`Column_priv`
)
SELECT
r.prefixedRole,
vTplHost,
t.`Db`,
t.`Table_name`,
t.`Grantor`,
MAX(t.`Timestamp`),
IFNULL(GROUP_CONCAT(NULLIF(t.`Table_priv`, '')), ''),
IFNULL(GROUP_CONCAT(NULLIF(t.`Column_priv`, '')), '')
FROM tRoleInherit r
JOIN mysql.tables_priv t
ON t.`User` = r.inheritsFrom
AND t.`Host`= vRoleHost
GROUP BY r.prefixedRole, t.`Db`, t.`Table_name`;
-- Copy column level privileges
INSERT INTO mysql.columns_priv (
`User`,
`Host`,
`Db`,
`Table_name`,
`Column_name`,
`Timestamp`,
`Column_priv`
)
SELECT
r.prefixedRole,
vTplHost,
t.`Db`,
t.`Table_name`,
t.`Column_name`,
MAX(t.`Timestamp`),
IFNULL(GROUP_CONCAT(NULLIF(t.`Column_priv`, '')), '')
FROM tRoleInherit r
JOIN mysql.columns_priv t
ON t.`User` = r.inheritsFrom
AND t.`Host`= vRoleHost
GROUP BY r.prefixedRole, t.`Db`, t.`Table_name`, t.`Column_name`;
-- Copy routine privileges
INSERT IGNORE INTO mysql.procs_priv (
`User`,
`Host`,
`Db`,
`Routine_name`,
`Routine_type`,
`Grantor`,
`Timestamp`,
`Proc_priv`
)
SELECT
r.prefixedRole,
vTplHost,
t.`Db`,
t.`Routine_name`,
t.`Routine_type`,
t.`Grantor`,
t.`Timestamp`,
t.`Proc_priv`
FROM tRoleInherit r
JOIN mysql.procs_priv t
ON t.`User` = r.inheritsFrom
AND t.`Host`= vRoleHost;
-- Free memory
DROP TEMPORARY TABLE
tRole,
tRoleInherit;
FLUSH PRIVILEGES;
END$$
DELIMITER ;

View File

@ -1,36 +0,0 @@
ALTER TABLE account.sambaConfig ADD adUser VARCHAR(255) DEFAULT NULL NULL COMMENT 'Active directory user';
ALTER TABLE account.sambaConfig ADD adPassword varchar(255) DEFAULT NULL NULL COMMENT 'Active directory password';
ALTER TABLE account.sambaConfig ADD userDn varchar(255) DEFAULT NULL NULL COMMENT 'The base DN for users';
ALTER TABLE account.sambaConfig DROP COLUMN uidBase;
ALTER TABLE account.sambaConfig CHANGE sshPass sshPassword varchar(255) DEFAULT NULL NULL COMMENT 'The SSH password';
ALTER TABLE account.ldapConfig DROP COLUMN `filter`;
ALTER TABLE account.ldapConfig CHANGE baseDn userDn varchar(255) DEFAULT NULL NULL COMMENT 'The base DN to do the query';
ALTER TABLE account.ldapConfig CHANGE host server varchar(255) NOT NULL COMMENT 'The hostname of LDAP server';
ALTER TABLE account.ldapConfig MODIFY COLUMN password varchar(255) NOT NULL COMMENT 'The LDAP password';
-- Updated
ALTER TABLE account.sambaConfig DROP COLUMN sshUser;
ALTER TABLE account.sambaConfig DROP COLUMN sshPassword;
ALTER TABLE account.sambaConfig CHANGE host adController varchar(255) DEFAULT NULL NULL COMMENT 'The hosname of domain controller';
ALTER TABLE account.sambaConfig MODIFY COLUMN adController varchar(255) DEFAULT NULL NULL COMMENT 'The hosname of domain controller';
ALTER TABLE account.sambaConfig DROP COLUMN userDn;
ALTER TABLE account.sambaConfig ADD adDomain varchar(255) NOT NULL AFTER id;
ALTER TABLE account.sambaConfig ADD verifyCert TINYINT UNSIGNED NOT NULL DEFAULT TRUE AFTER adPassword;
ALTER TABLE account.sambaConfig MODIFY COLUMN adController varchar(255) NOT NULL COMMENT 'The hosname of domain controller';
ALTER TABLE account.user
ADD COLUMN `realm` varchar(512) CHARACTER SET utf8 DEFAULT NULL AFTER id,
ADD COLUMN `emailVerified` tinyint(1) DEFAULT NULL AFTER email,
ADD COLUMN `verificationToken` varchar(512) DEFAULT NULL AFTER emailVerified;
DROP TABLE salix.user;
CREATE OR REPLACE VIEW salix.User
AS SELECT id, realm, name AS username, bcryptPassword AS password, email, emailVerified, verificationToken
FROM account.user;
ALTER TABLE account.`user`
MODIFY COLUMN bcryptPassword varchar(512) DEFAULT NULL NULL;

View File

@ -1,20 +0,0 @@
CREATE TABLE `vn`.`supplierLog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`originFk` int(11) NOT NULL,
`userFk` int(10) unsigned NOT NULL,
`action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL,
`creationDate` timestamp NULL DEFAULT current_timestamp(),
`description` text CHARACTER SET utf8 DEFAULT NULL,
`changedModel` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`oldInstance` text COLLATE utf8_unicode_ci DEFAULT NULL,
`newInstance` text COLLATE utf8_unicode_ci DEFAULT NULL,
`changedModelId` int(11) DEFAULT NULL,
`changedModelValue` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `logSupplier_ibfk_1` (`originFk`),
KEY `supplierLog_ibfk_2` (`userFk`),
CONSTRAINT `supplierLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `supplier` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `supplierLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

View File

@ -1,24 +0,0 @@
CREATE TABLE `vn`.`supplierContact` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`supplierFk` INT(11) NULL DEFAULT NULL,
`phone` VARCHAR(16) NULL DEFAULT NULL,
`mobile` VARCHAR(16) NULL DEFAULT NULL,
`email` VARCHAR(255) NULL DEFAULT NULL,
`observation` TEXT NULL DEFAULT NULL,
`name` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
ALTER TABLE `vn`.`supplierContact`
ADD CONSTRAINT `supplier_id`
FOREIGN KEY (`supplierFk`)
REFERENCES `vn`.`supplier` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE;
INSERT INTO vn.supplierContact(supplierFk,phone,mobile,email,observation,`name`)
SELECT r.Id_Proveedor,c.Telefono,c.Movil,c.email,c.Notas,concat(c.Nombre," ", IFNULL(c.Apellidos,""))
FROM vn2008.Contactos c
JOIN vn2008.Relaciones r ON r.Id_Contacto = c.Id_Contacto
JOIN vn.supplier s ON s.id = r.Id_Proveedor;

View File

@ -1,25 +0,0 @@
DROP TRIGGER IF EXISTS `vn`.`ticket_afterUpdate`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `ticket_afterUpdate`
AFTER UPDATE ON `ticket`
FOR EACH ROW
BEGIN
IF !(NEW.id <=> OLD.id)
OR !(NEW.warehouseFk <=> OLD.warehouseFk)
OR !(NEW.shipped <=> OLD.shipped) THEN
CALL stock.log_add('ticket', NEW.id, OLD.id);
END IF;
IF NEW.clientFk = 2067 AND !(NEW.clientFk <=> OLD.clientFk) THEN
-- Fallo que se insertan no se sabe como tickets en este cliente
INSERT INTO vn.mail SET
`sender` = 'jgallego@verdnatura.es',
`replyTo` = 'jgallego@verdnatura.es',
`subject` = 'Modificado ticket al cliente 2067',
`body` = CONCAT(account.myUserGetName(), ' ha modificado el ticket ',
NEW.id);
END IF;
END$$
DELIMITER ;

View File

@ -1,107 +0,0 @@
USE `vn`;
DROP procedure IF EXISTS `ticket_componentPreview`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_componentPreview`(
vTicketFk INT,
vLanded DATE,
vAddressFk INT,
vZoneFk INT,
vWarehouseFk SMALLINT)
BEGIN
/**
* Calcula los componentes de los articulos de un ticket
*
* @param vTicketFk id del ticket
* @param vLanded nueva fecha de entrega
* @param vAddressFk nuevo consignatario
* @param vZoneFk nueva zona
* @param vWarehouseFk nuevo warehouse
*
* @return tmp.ticketComponentPreview (warehouseFk, itemFk, componentFk, cost)
*/
DECLARE vHasDataChanged BOOL DEFAULT FALSE;
DECLARE vHasAddressChanged BOOL;
DECLARE vHasZoneChanged BOOL DEFAULT FALSE;
DECLARE vHasWarehouseChanged BOOL DEFAULT FALSE;
DECLARE vShipped DATE;
DECLARE vAddressTypeRateFk INT DEFAULT NULL;
DECLARE vAgencyModeTypeRateFk INT DEFAULT NULL;
DECLARE vHasChangeAll BOOL DEFAULT FALSE;
SELECT DATE(landed) <> vLanded,
addressFk <> vAddressFk,
zoneFk <> vZoneFk,
warehouseFk <> vWarehouseFk
INTO
vHasDataChanged,
vHasAddressChanged,
vHasZoneChanged,
vHasWarehouseChanged
FROM vn.ticket t
WHERE t.id = vTicketFk;
IF vHasDataChanged OR vHasWarehouseChanged THEN
SET vHasChangeAll = TRUE;
END IF;
IF vHasAddressChanged THEN
SET vAddressTypeRateFk = 5;
END IF;
IF vHasZoneChanged THEN
SET vAgencyModeTypeRateFk = 6;
END IF;
SELECT TIMESTAMPADD(DAY, -travelingDays, vLanded) INTO vShipped
FROM zone
WHERE id = vZoneFk;
CALL buyUltimate(vWarehouseFk, vShipped);
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot ENGINE = MEMORY (
SELECT
vWarehouseFk AS warehouseFk,
NULL AS available,
s.itemFk,
bu.buyFk,
vZoneFk zoneFk
FROM sale s
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
WHERE s.ticketFk = vTicketFk
GROUP BY bu.warehouseFk, bu.itemFk);
CALL catalog_componentPrepare();
CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
REPLACE INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost)
SELECT t.warehouseFk, s.itemFk, sc.componentFk, sc.value
FROM saleComponent sc
JOIN sale s ON s.id = sc.saleFk
JOIN ticket t ON t.id = s.ticketFk
JOIN `component` c ON c.id = sc.componentFk
WHERE s.ticketFk = vTicketFk
AND (c.isRenewable = FALSE
OR
(NOT vHasChangeAll
AND (NOT (c.typeFk <=> vAddressTypeRateFk
OR c.typeFk <=> vAgencyModeTypeRateFk))));
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentPreview;
CREATE TEMPORARY TABLE tmp.ticketComponentPreview
SELECT * FROM tmp.ticketComponent;
CALL catalog_componentPurge();
DROP TEMPORARY TABLE tmp.buyUltimate;
IF vShipped IS NULL THEN
CALL util.throw('NO_ZONE_AVAILABLE');
END IF;
END$$
DELIMITER ;

View File

@ -1,12 +0,0 @@
UPDATE `salix`.`ACL` SET `principalId` = 'deliveryBoss' WHERE (`id` = '194');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '97');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '100');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '103');
UPDATE `salix`.`ACL` SET `principalId` = 'claimManager' WHERE (`id` = '202');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Town', '*', 'WRITE', 'ALLOW', 'ROLE', 'deliveryBoss');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Province', '*', 'WRITE', 'ALLOW', 'ROLE', 'deliveryBoss');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Supplier', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Supplier', '*', 'WRITE', 'ALLOW', 'ROLE', 'administrative');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SupplierLog', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SupplierContact', '*', 'WRITE', 'ALLOW', 'ROLE', 'administrative');

View File

@ -1,3 +0,0 @@
UPDATE `vn`.`claimState` SET `roleFk` = '72' WHERE (`id` = '3');
UPDATE `vn`.`claimState` SET `roleFk` = '72' WHERE (`id` = '4');
UPDATE `vn`.`claimState` SET `roleFk` = '72' WHERE (`id` = '5');

View File

@ -1,5 +0,0 @@
ALTER TABLE `hedera`.`imageCollection`
ADD COLUMN `readRoleFk` VARCHAR(45) NULL DEFAULT NULL AFTER `column`;
update `hedera`.`imageCollection` set `readRoleFk` = 1;

View File

@ -1,9 +0,0 @@
ALTER TABLE `vn`.`observationType`
ADD COLUMN `code` VARCHAR(45) NOT NULL AFTER `description`;
UPDATE `vn`.`observationType` SET `code` = 'itemPicker' WHERE (`id` = '1');
UPDATE `vn`.`observationType` SET `code` = 'packager' WHERE (`id` = '2');
UPDATE `vn`.`observationType` SET `code` = 'salesPerson' WHERE (`id` = '4');
UPDATE `vn`.`observationType` SET `code` = 'administrative' WHERE (`id` = '5');
UPDATE `vn`.`observationType` SET `code` = 'weight' WHERE (`id` = '6');
UPDATE `vn`.`observationType` SET `code` = 'delivery' WHERE (`id` = '3');

View File

@ -1,20 +0,0 @@
CREATE TABLE `vn`.`supplierLog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`originFk` int(11) NOT NULL,
`userFk` int(10) unsigned NOT NULL,
`action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL,
`creationDate` timestamp NULL DEFAULT current_timestamp(),
`description` text CHARACTER SET utf8 DEFAULT NULL,
`changedModel` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`oldInstance` text COLLATE utf8_unicode_ci DEFAULT NULL,
`newInstance` text COLLATE utf8_unicode_ci DEFAULT NULL,
`changedModelId` int(11) DEFAULT NULL,
`changedModelValue` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `logSupplier_ibfk_1` (`originFk`),
KEY `supplierLog_ibfk_2` (`userFk`),
CONSTRAINT `supplierLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `supplier` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `supplierLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

View File

@ -1,25 +0,0 @@
DROP TRIGGER IF EXISTS `vn`.`ticket_afterUpdate`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `ticket_afterUpdate`
AFTER UPDATE ON `ticket`
FOR EACH ROW
BEGIN
IF !(NEW.id <=> OLD.id)
OR !(NEW.warehouseFk <=> OLD.warehouseFk)
OR !(NEW.shipped <=> OLD.shipped) THEN
CALL stock.log_add('ticket', NEW.id, OLD.id);
END IF;
IF NEW.clientFk = 2067 AND !(NEW.clientFk <=> OLD.clientFk) THEN
-- Fallo que se insertan no se sabe como tickets en este cliente
INSERT INTO vn.mail SET
`sender` = 'jgallego@verdnatura.es',
`replyTo` = 'jgallego@verdnatura.es',
`subject` = 'Modificado ticket al cliente 2067',
`body` = CONCAT(account.myUserGetName(), ' ha modificado el ticket ',
NEW.id);
END IF;
END$$
DELIMITER ;

View File

@ -1,107 +0,0 @@
USE `vn`;
DROP procedure IF EXISTS `ticket_componentPreview`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_componentPreview`(
vTicketFk INT,
vLanded DATE,
vAddressFk INT,
vZoneFk INT,
vWarehouseFk SMALLINT)
BEGIN
/**
* Calcula los componentes de los articulos de un ticket
*
* @param vTicketFk id del ticket
* @param vLanded nueva fecha de entrega
* @param vAddressFk nuevo consignatario
* @param vZoneFk nueva zona
* @param vWarehouseFk nuevo warehouse
*
* @return tmp.ticketComponentPreview (warehouseFk, itemFk, componentFk, cost)
*/
DECLARE vHasDataChanged BOOL DEFAULT FALSE;
DECLARE vHasAddressChanged BOOL;
DECLARE vHasZoneChanged BOOL DEFAULT FALSE;
DECLARE vHasWarehouseChanged BOOL DEFAULT FALSE;
DECLARE vShipped DATE;
DECLARE vAddressTypeRateFk INT DEFAULT NULL;
DECLARE vAgencyModeTypeRateFk INT DEFAULT NULL;
DECLARE vHasChangeAll BOOL DEFAULT FALSE;
SELECT DATE(landed) <> vLanded,
addressFk <> vAddressFk,
zoneFk <> vZoneFk,
warehouseFk <> vWarehouseFk
INTO
vHasDataChanged,
vHasAddressChanged,
vHasZoneChanged,
vHasWarehouseChanged
FROM vn.ticket t
WHERE t.id = vTicketFk;
IF vHasDataChanged OR vHasWarehouseChanged THEN
SET vHasChangeAll = TRUE;
END IF;
IF vHasAddressChanged THEN
SET vAddressTypeRateFk = 5;
END IF;
IF vHasZoneChanged THEN
SET vAgencyModeTypeRateFk = 6;
END IF;
SELECT TIMESTAMPADD(DAY, -travelingDays, vLanded) INTO vShipped
FROM zone
WHERE id = vZoneFk;
CALL buyUltimate(vWarehouseFk, vShipped);
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot ENGINE = MEMORY (
SELECT
vWarehouseFk AS warehouseFk,
NULL AS available,
s.itemFk,
bu.buyFk,
vZoneFk zoneFk
FROM sale s
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
WHERE s.ticketFk = vTicketFk
GROUP BY bu.warehouseFk, bu.itemFk);
CALL catalog_componentPrepare();
CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
REPLACE INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost)
SELECT t.warehouseFk, s.itemFk, sc.componentFk, sc.value
FROM saleComponent sc
JOIN sale s ON s.id = sc.saleFk
JOIN ticket t ON t.id = s.ticketFk
JOIN `component` c ON c.id = sc.componentFk
WHERE s.ticketFk = vTicketFk
AND (c.isRenewable = FALSE
OR
(NOT vHasChangeAll
AND (NOT (c.typeFk <=> vAddressTypeRateFk
OR c.typeFk <=> vAgencyModeTypeRateFk))));
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentPreview;
CREATE TEMPORARY TABLE tmp.ticketComponentPreview
SELECT * FROM tmp.ticketComponent;
CALL catalog_componentPurge();
DROP TEMPORARY TABLE tmp.buyUltimate;
IF vShipped IS NULL THEN
CALL util.throw('NO_ZONE_AVAILABLE');
END IF;
END$$
DELIMITER ;

View File

@ -1,43 +0,0 @@
DROP PROCEDURE IF EXISTS `vn`.`timeControl_calculate`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`timeControl_calculate`(vDatedFrom DATETIME, vDatedTo DATETIME)
BEGIN
SET @vIsOdd := TRUE;
SET @vUser := NULL;
SET @vDated := NULL;
DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate;
CREATE TEMPORARY TABLE tmp.timeControlCalculate
SELECT
userFk,
dated,
IF( timeWork >= 18000, @timeWork:=timeWork + 1200, @timeWork:=timeWork) timeWorkSeconds,
SEC_TO_TIME(@timeWork ) timeWorkSexagesimal,
@timeWork / 3600 timeWorkDecimal,
timed
FROM (SELECT SUM(timeWork) timeWork,
userFk,
dated,
GROUP_CONCAT(DATE_FORMAT(sub.timed,"%H:%i") ORDER BY sub.timed ASC SEPARATOR ' - ') timed
FROM (SELECT IF(@vUser = wtc.userFk, @vUser :=@vUser, @vUser := wtc.userFk),
IF(@vIsOdd, @vIsOdd := FALSE, @vIsOdd := TRUE),
IF(direction='in', @vIsOdd := TRUE, @vIsOdd := @vIsOdd),
IF(@vIsOdd, @vLastTimed:=UNIX_TIMESTAMP(timed),@vLastTimed:=@vLastTimed),
IF(@vIsOdd, 0, UNIX_TIMESTAMP(timed)-@vLastTimed) timeWork,
IF(direction='in', @vDated := DATE(wtc.timed), @vDated :=@vDated) dated,
wtc.timed timed,
wtc.userFk,
direction
FROM (SELECT DISTINCT(wtc.id), wtc.userFk, wtc.timed, wtc.direction
FROM workerTimeControl wtc
JOIN tmp.`user` w ON w.userFk = wtc.userFk
WHERE wtc.timed BETWEEN vDatedFrom AND vDatedTo
ORDER BY userFk, timed ASC
) wtc
WHERE wtc.timed BETWEEN vDatedFrom AND vDatedTo
) sub
GROUP BY userFk, dated
)sub2;
END$$
DELIMITER ;

View File

@ -1,2 +0,0 @@
ALTER TABLE `account`.`user`
ADD COLUMN `image` VARCHAR(255) NULL AFTER `password`;

View File

@ -1,20 +0,0 @@
CREATE TABLE `vn`.supplierFreighter
(
supplierFk INT NOT NULL,
CONSTRAINT supplierFreighter_pk
PRIMARY KEY (supplierFk),
CONSTRAINT supplier_id_fk
FOREIGN KEY (supplierFk) REFERENCES supplier (id)
ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (286);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (454);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (582);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (470);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (775);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (812);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (1112);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (1242);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (1281);
INSERT IGNORE INTO `vn`.supplierFreighter (supplierFk) VALUES (1765);

View File

@ -1,7 +0,0 @@
ALTER TABLE `vn`.travel
DROP FOREIGN KEY travel_ibfk_4;
ALTER TABLE `vn`.travel
ADD CONSTRAINT supplierFreighter_fk_4
FOREIGN KEY (cargoSupplierFk) REFERENCES supplierFreighter (supplierFk)
ON UPDATE CASCADE ON DELETE SET NULL;

View File

@ -1,20 +0,0 @@
CREATE TABLE `vn`.continent
(
id TINYINT(4) AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
code VARCHAR(2) NOT NULL COLLATE utf8_general_ci,
CONSTRAINT continent_pk
PRIMARY KEY (id)
)
COMMENT 'World continents';
CREATE UNIQUE INDEX continent_name_uindex
ON `vn`.continent (name);
INSERT IGNORE INTO `vn`.continent (`name`, `code`)
VALUES
('Asia', 'AS'),
('América', 'AM'),
('África', 'AF'),
('Europa', 'EU'),
('Oceanía', 'OC');

View File

@ -1,13 +0,0 @@
ALTER TABLE `vn`.`country`
ADD COLUMN `continentFk` TINYINT(4) NULL AFTER `ibanLength`,
ADD INDEX `continent_id_fk_idx` (`continentFk` ASC);
ALTER TABLE `vn`.`country`
ADD CONSTRAINT `continent_id_fk`
FOREIGN KEY (`continentFk`)
REFERENCES `vn`.`continent` (`id`)
ON DELETE NO ACTION
ON UPDATE CASCADE;
UPDATE `vn`.`country` SET `continentFk` = '2' WHERE (`id` = '11');
UPDATE `vn`.`country` SET `continentFk` = '2' WHERE (`id` = '13');

View File

@ -1 +0,0 @@
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) VALUES ('Image', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee');

View File

@ -1,14 +0,0 @@
CREATE TABLE `vn`.`entryObservation` (
id int NOT NULL AUTO_INCREMENT,
entryFk int NOT NULL,
observationTypeFk TINYINT(3) UNSIGNED,
description TEXT,
PRIMARY KEY (id),
CONSTRAINT entry_id_entryFk
FOREIGN KEY (entryFk) REFERENCES entry(id),
CONSTRAINT observationType_id_observationTypeFk
FOREIGN KEY (observationTypeFk) REFERENCES observationType(id)
);
ALTER TABLE `vn`.`entryObservation`
ADD UNIQUE INDEX `entryFk_observationTypeFk_UNIQUE` (`entryFk` ASC,`observationTypeFk` ASC);

View File

@ -1,135 +0,0 @@
-- DROP PROCEDURE `vn`.`clonTravelComplete`;
DELIMITER $$
USE `vn`$$
CREATE
DEFINER = root@`%` PROCEDURE `vn`.`travel_cloneWithEntries`(IN vTravelFk INT, IN vDateStart DATE, IN vDateEnd DATE,
IN vRef VARCHAR(255), OUT vNewTravelFk INT)
BEGIN
DECLARE vEntryNew INT;
DECLARE vDone BOOLEAN DEFAULT FALSE;
DECLARE vAuxEntryFk INT;
DECLARE vRsEntry CURSOR FOR
SELECT e.id
FROM entry e
JOIN travel t
ON t.id = e.travelFk
WHERE e.travelFk = vTravelFk;
DECLARE vRsBuy CURSOR FOR
SELECT b.*
FROM buy b
JOIN entry e
ON b.entryFk = e.id
WHERE e.travelFk = vNewTravelFk and b.entryFk=vNewTravelFk
ORDER BY e.id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
INSERT INTO travel (shipped,landed, warehouseInFk, warehouseOutFk, agencyFk, ref, isDelivered, isReceived, m3, kg)
SELECT vDateStart, vDateEnd,warehouseInFk, warehouseOutFk, agencyFk, vRef, isDelivered, isReceived, m3, kg
FROM travel
WHERE id = vTravelFk;
SET vNewTravelFk = LAST_INSERT_ID();
SET vDone = FALSE;
OPEN vRsEntry ;
FETCH vRsEntry INTO vAuxEntryFk;
WHILE NOT vDone DO
INSERT INTO entry (supplierFk,
ref,
isInventory,
isConfirmed,
isOrdered,
isRaid,
commission,
created,
evaNotes,
travelFk,
currencyFk,
companyFk,
gestDocFk,
invoiceInFk)
SELECT supplierFk,
ref,
isInventory,
isConfirmed,
isOrdered,
isRaid,
commission,
created,
evaNotes,
vNewTravelFk,
currencyFk,
companyFk,
gestDocFk,
invoiceInFk
FROM entry
WHERE id = vAuxEntryFk;
SET vEntryNew = LAST_INSERT_ID();
INSERT INTO buy (entryFk,
itemFk,
quantity,
buyingValue,
packageFk,
stickers,
freightValue,
packageValue,
comissionValue,
packing,
`grouping`,
groupingMode,
location,
price1,
price2,
price3,
minPrice,
producer,
printedStickers,
isChecked,
weight)
SELECT vEntryNew,
itemFk,
quantity,
buyingValue,
packageFk,
stickers,
freightValue,
packageValue,
comissionValue,
packing,
`grouping`,
groupingMode,
location,
price1,
price2,
price3,
minPrice,
producer,
printedStickers,
isChecked,
weight
FROM buy
WHERE entryFk = vAuxEntryFk;
FETCH vRsEntry INTO vAuxEntryFk;
END WHILE;
CLOSE vRsEntry;
COMMIT;
END;$$
DELIMITER ;

View File

@ -1,18 +0,0 @@
CREATE TABLE `vn`.`zoneLog` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`originFk` int(10) NOT NULL,
`userFk` int(10) unsigned DEFAULT NULL,
`action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL,
`creationDate` timestamp NULL DEFAULT current_timestamp(),
`description` text CHARACTER SET utf8 DEFAULT NULL,
`changedModel` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`oldInstance` text COLLATE utf8_unicode_ci DEFAULT NULL,
`newInstance` text COLLATE utf8_unicode_ci DEFAULT NULL,
`changedModelId` int(11) DEFAULT NULL,
`changedModelValue` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `originFk` (`originFk`),
KEY `userFk` (`userFk`),
CONSTRAINT `zoneLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `vn`.`zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `zoneLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

View File

@ -1,13 +0,0 @@
INSERT INTO account.role (id, name, description)
VALUES
(74, 'userPhotos', 'Privilegios para subir fotos de usuario'),
(75, 'catalogPhotos', 'Privilegios para subir fotos del catálogo');
INSERT INTO account.roleInherit (role, inheritsFrom)
VALUES
(37, (SELECT id FROM account.role WHERE name = 'userPhotos')),
(51, (SELECT id FROM account.role WHERE name = 'userPhotos')),
(51, (SELECT id FROM account.role WHERE name = 'catalogPhotos')),
(35, (SELECT id FROM account.role WHERE name = 'catalogPhotos'));
CALL account.role_sync();

View File

@ -1,27 +0,0 @@
ALTER TABLE `hedera`.`imageCollection`
ADD writeRoleFk INT UNSIGNED NULL DEFAULT 1;
ALTER TABLE `hedera`.`imageCollection`
ADD CONSTRAINT role_id_writeRoleFk
FOREIGN KEY (writeRoleFk) REFERENCES account.role (id)
ON UPDATE CASCADE;
ALTER TABLE `hedera`.`imageCollection` modify readRoleFk INT UNSIGNED default 1 null;
ALTER TABLE `hedera`.`imageCollection`
ADD CONSTRAINT role_id_readRoleFk
FOREIGN KEY (readRoleFk) REFERENCES account.role (id)
ON UPDATE CASCADE;
UPDATE hedera.imageCollection t SET t.writeRoleFk = (
SELECT id FROM `account`.`role` WHERE name = 'catalogPhotos'
)
WHERE t.name = 'catalog';
UPDATE hedera.imageCollection t SET t.writeRoleFk = (
SELECT id FROM `account`.`role` WHERE name = 'userPhotos'
)
WHERE t.name = 'user';
UPDATE hedera.imageCollection t SET t.writeRoleFk = 9
WHERE t.name IN ('link', 'news');

View File

@ -1,19 +0,0 @@
DROP TRIGGER IF EXISTS `vn`.`itemTag_afterUpdate`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`itemTag_afterUpdate`
AFTER UPDATE ON `itemTag` FOR EACH ROW
trig: BEGIN
IF @isTriggerDisabled THEN
LEAVE trig;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp.item;
CREATE TEMPORARY TABLE tmp.item
SELECT NEW.itemFk id;
CALL item_refreshTags();
DROP TEMPORARY TABLE tmp.item;
END$$
DELIMITER ;

View File

@ -1,5 +0,0 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('FixedPrice', '*', '*', 'ALLOW', 'ROLE', 'buyer');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('PayDem', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Client', 'createReceipt', '*', 'ALLOW', 'ROLE', 'administrative');
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
VALUES ('PrintServerQueue', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee');

View File

@ -1,82 +0,0 @@
DROP PROCEDURE IF EXISTS vn.ledger_doCompensation;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`ledger_doCompensation`(vDated DATE, vCompensationAccount VARCHAR(10) , vBankFk VARCHAR(10), vConcept VARCHAR(255), vAmount DECIMAL(10,2), vCompanyFk INT, vOriginalAccount VARCHAR(10))
BEGIN
/**
* Compensa un pago o un recibo insertando en contabilidad
*
* @param vDated fecha en la cual se anota
* @param vCompensationAccount cuenta contable contra la que se compensa
* @param vBankFk banco de la compensacion
* @param vConcept descripcion
* @param vAmount cantidad que se compensa
* @param vCompany empresa
* @param vOriginalAccount cuenta contable desde la cual se compensa
*
*/
DECLARE vNewBookEntry INT;
DECLARE vIsClientCompensation INT;
DECLARE vClientFk INT;
DECLARE vSupplierFk INT;
DECLARE vIsOriginalAClient BOOL;
DECLARE vPayMethodCompensation INT;
CALL ledger_next(vNewBookEntry);
SELECT COUNT(id) INTO vIsOriginalAClient FROM client WHERE accountingAccount LIKE vOriginalAccount COLLATE utf8_general_ci;
SELECT id, COUNT(id) INTO vClientFk, vIsClientCompensation
FROM client
WHERE accountingAccount LIKE vCompensationAccount COLLATE utf8_general_ci;
SET @vAmount1:= 0.0;
SET @vAmount2:= 0.0;
INSERT INTO XDiario (ASIEN, FECHA, SUBCTA, CONTRA, CONCEPTO, EURODEBE, EUROHABER, empresa_id)
VALUES ( vNewBookEntry,
vDated,
vOriginalAccount,
vCompensationAccount,
vConcept,
@vAmount1:= IF(
(vIsOriginalAClient OR NOT vIsOriginalAClient)
AND vAmount > 0,
0,
ABS(vAmount)
),
@vAmount2:= IF(@vAmount1,
0,
ABS(vAmount)
),
vCompanyFk
),
( vNewBookEntry,
vDated,
vCompensationAccount,
vOriginalAccount,
vConcept,
@vAmount2,
@vAmount1,
vCompanyFk);
IF vIsClientCompensation THEN
IF vIsOriginalAClient THEN
SET vAmount = -vAmount;
END IF;
INSERT INTO receipt(invoiceFk, amountPaid, payed, bankFk, companyFk, clientFk, isConciliate)
VALUES (vConcept, vAmount, vDated, vBankFk, vCompanyFk, vClientFk, TRUE);
ELSE
IF NOT vIsOriginalAClient THEN
SET vAmount = -vAmount;
END IF;
SELECT id INTO vSupplierFk FROM supplier WHERE `account` LIKE vCompensationAccount COLLATE utf8_general_ci;
SELECT id INTO vPayMethodCompensation FROM payMethod WHERE `code` = 'compensation';
INSERT INTO payment (received, dueDated, supplierFk, amount, bankFk, payMethodFk, concept, companyFk, isConciliated)
VALUES(vDated, vDated, vSupplierFk, vAmount, vBankFk, vPayMethodCompensation, vConcept, vCompanyFk, TRUE);
END IF;
END$$
DELIMITER ;

View File

@ -1,17 +0,0 @@
DROP TRIGGER IF EXISTS vn.receipt_beforInsert;
DELIMITER $$
$$
CREATE TRIGGER receipt_beforInsert
BEFORE INSERT
ON receipt FOR EACH ROW
BEGIN
SELECT isAutoConciliated INTO @isAutoConciliated
FROM accounting a
JOIN accountingType at2 ON at2.id = a.accountingTypeFk
WHERE a.id =NEW.bankFk;
SET NEW.isConciliate = @isAutoConciliated;
END
$$
DELIMITER ;

View File

@ -0,0 +1,5 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('SupplierAccount', '*', '*', 'ALLOW', 'ROLE', 'administrative'),
('Entry', '*', '*', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', '*', '*', 'ALLOW', 'ROLE', 'administrative');

View File

@ -0,0 +1,137 @@
DROP PROCEDURE `vn`.`item_getBalance`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`item_getBalance`(IN vItemId INT, IN vWarehouse INT)
BEGIN
DECLARE vDateInventory DATETIME;
DECLARE vCurdate DATE DEFAULT CURDATE();
DECLARE vDayEnd DATETIME DEFAULT util.dayEnd(vCurdate);
SELECT inventoried INTO vDateInventory FROM config;
SET @a = 0;
SET @currentLineFk = 0;
SET @shipped = '';
SELECT DATE(@shipped:= shipped) shipped,
alertLevel,
stateName,
origin,
reference,
clientFk,
name,
`in`,
`out`,
@a := @a + IFNULL(`in`,0) - IFNULL(`out`,0) as balance,
@currentLineFk := IF (@shipped < CURDATE()
OR (@shipped = CURDATE() AND (isPicked OR alertLevel >= 2)),
lineFk,@currentLineFk) lastPreparedLineFk,
isTicket,
lineFk,
isPicked,
clientType
FROM
( SELECT tr.landed AS shipped,
b.quantity AS `in`,
NULL AS `out`,
al.alertLevel AS alertLevel,
st.name AS stateName,
s.name AS name,
e.ref AS reference,
e.id AS origin,
s.id AS clientFk,
IF(al.alertLevel = 3, TRUE, FALSE) isPicked,
FALSE AS isTicket,
b.id lineFk,
NULL `order`,
NULL AS clientType
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel tr ON tr.id = e.travelFk
JOIN supplier s ON s.id = e.supplierFk
JOIN alertLevel al ON al.alertLevel =
CASE
WHEN tr.shipped < CURDATE() THEN 3
WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
ELSE 0
END
JOIN state st ON st.code = al.code
WHERE tr.landed >= vDateInventory
AND vWarehouse = tr.warehouseInFk
AND b.itemFk = vItemId
AND e.isInventory = FALSE
AND e.isRaid = FALSE
UNION ALL
SELECT tr.shipped,
NULL as `in`,
b.quantity AS `out`,
al.alertLevel AS alertLevel,
st.name AS stateName,
s.name AS name,
e.ref AS reference,
e.id AS origin,
s.id AS clientFk,
IF(al.alertLevel = 3, TRUE, FALSE) isPicked,
FALSE AS isTicket,
b.id,
NULL `order`,
NULL AS clientType
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel tr ON tr.id = e.travelFk
JOIN warehouse w ON w.id = tr.warehouseOutFk
JOIN supplier s ON s.id = e.supplierFk
JOIN alertLevel al ON al.alertLevel =
CASE
WHEN tr.shipped < CURDATE() THEN 3
WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
ELSE 0
END
JOIN state st ON st.code = al.code
WHERE tr.shipped >= vDateInventory
AND vWarehouse =tr.warehouseOutFk
AND s.id <> 4
AND b.itemFk = vItemId
AND e.isInventory = FALSE
AND w.isFeedStock = FALSE
AND e.isRaid = FALSE
UNION ALL
SELECT DATE(t.shipped),
NULL as `in`,
s.quantity AS `out`,
al.alertLevel AS alertLevel,
st.name AS stateName,
t.nickname AS name,
t.refFk AS reference,
t.id AS origin,
t.clientFk,
stk.id AS isPicked,
TRUE AS isTicket,
s.id,
st.`order`,
ct.code AS clientType
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
LEFT JOIN ticketState ts ON ts.ticket = t.id
LEFT JOIN state st ON st.code = ts.code
JOIN client c ON c.id = t.clientFk
JOIN clientType ct ON ct.id = c.clientTypeFk
JOIN alertLevel al ON al.alertLevel =
CASE
WHEN t.shipped < curdate() THEN 3
WHEN t.shipped > util.dayEnd(curdate()) THEN 0
ELSE IFNULL(ts.alertLevel, 0)
END
LEFT JOIN state stPrep ON stPrep.`code` = 'PREPARED'
LEFT JOIN saleTracking stk ON stk.saleFk = s.id AND stk.stateFk = stPrep.id
WHERE t.shipped >= vDateInventory
AND s.itemFk = vItemId
AND vWarehouse =t.warehouseFk
ORDER BY shipped, alertLevel DESC, isTicket, `order` DESC, isPicked DESC, `in` DESC, `out` DESC
) AS itemDiary;
END$$
DELIMITER ;

View File

@ -0,0 +1,2 @@
ALTER TABLE `vn`.`supplier` ADD COLUMN `workerFk` INT(11) NULL DEFAULT NULL COMMENT 'Responsible for approving invoices' AFTER `isTrucker`;
ALTER TABLE `vn`.`supplier` ADD CONSTRAINT `supplier_workerFk` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE;

View File

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

View File

@ -0,0 +1,20 @@
CREATE TABLE `salix`.`module` (
`code` VARCHAR(45) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `salix`.`module`(`code`)
VALUES
('Items'),
('Orders'),
('Clients'),
('Entries'),
('Travels'),
('Invoices out'),
('Suppliers'),
('Claims'),
('Routes'),
('Tickets'),
('Workers'),
('Users'),
('Zones');

View File

@ -0,0 +1,10 @@
CREATE TABLE `vn`.`starredModule` (
`id` INT(11) unsigned NOT NULL AUTO_INCREMENT,
`workerFk` INT(10) NOT NULL,
`moduleFk` VARCHAR(45) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `starred_workerFk` (`workerFk`),
KEY `starred_moduleFk` (`moduleFk`),
CONSTRAINT `starred_workerFk` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE,
CONSTRAINT `starred_moduleFk` FOREIGN KEY (`moduleFk`) REFERENCES `salix`.`module` (`code`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

File diff suppressed because one or more lines are too long

View File

@ -151,19 +151,19 @@ INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `isPrinted`, `priority`, `park
INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`,`code`) INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`,`code`)
VALUES VALUES
(1, 'CC y Polizas de crédito', NULL, NULL), (1, 'CC y Polizas de crédito', NULL, NULL),
(2, 'Cash', NULL, 'cash'), (2, 'Cash', 'Cash', 'cash'),
(3, 'Credit card', NULL, 'creditCard'), (3, 'Credit card', 'Credit Card', 'creditCard'),
(4, 'Finalcial lines', NULL, NULL), (4, 'Finalcial lines', NULL, NULL),
(5, 'Other products', NULL, NULL), (5, 'Other products', NULL, NULL),
(6, 'Loans', NULL, NULL), (6, 'Loans', NULL, NULL),
(7, 'Leasing', NULL, NULL), (7, 'Leasing', NULL, NULL),
(8, 'Compensations', 'Compensations', 'Compensations'); (8, 'Compensations', 'Compensations', 'compensation');
INSERT INTO `vn`.`bank`(`id`, `bank`, `account`, `cash`, `entityFk`, `isActive`, `currencyFk`) INSERT INTO `vn`.`bank`(`id`, `bank`, `account`, `cash`, `entityFk`, `isActive`, `currencyFk`)
VALUES VALUES
(1, 'Pay on receipt', '0000000000', 3, 0, 1, 1), (1, 'Pay on receipt', '5720000001', 3, 0, 1, 1),
(2, 'Cash', '1111111111', 2, 0, 1, 1), (2, 'Cash', '5700000001', 2, 0, 1, 1),
(3, 'Compensation', '0000000000', 8, 0, 1, 1); (3, 'Compensation', '4000000000', 8, 0, 1, 1);
INSERT INTO `vn`.`deliveryMethod`(`id`, `code`, `description`) INSERT INTO `vn`.`deliveryMethod`(`id`, `code`, `description`)
VALUES VALUES
@ -1233,11 +1233,11 @@ INSERT INTO `vn`.`annualAverageInvoiced`(`clientFk`, `invoiced`)
(104, 500), (104, 500),
(105, 5000); (105, 5000);
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`) INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`)
VALUES VALUES
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1), (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8), (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3); (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18);
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`) INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
VALUES VALUES
@ -1246,11 +1246,6 @@ INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email
(3, 2, 321654987, NULL, 'supplier2@email.es', NULL, NULL), (3, 2, 321654987, NULL, 'supplier2@email.es', NULL, NULL),
(4, 442, 321654987, NULL, NULL, 'observation442', NULL); (4, 442, 321654987, NULL, NULL, 'observation442', NULL);
INSERT INTO `vn`.`supplierFreighter` (`supplierFk`)
VALUES
(1),
(2);
INSERT INTO `cache`.`cache_calc`(`id`, `cache_id`, `cacheName`, `params`, `last_refresh`, `expires`, `created`, `connection_id`) INSERT INTO `cache`.`cache_calc`(`id`, `cache_id`, `cacheName`, `params`, `last_refresh`, `expires`, `created`, `connection_id`)
VALUES VALUES
(1, 2, 'available', CONCAT_WS('/',1,CURDATE()), CURRENT_TIMESTAMP(), DATE_ADD(CURRENT_TIMESTAMP(),INTERVAL 15 MINUTE), CURDATE(), NULL), (1, 2, 'available', CONCAT_WS('/',1,CURDATE()), CURRENT_TIMESTAMP(), DATE_ADD(CURRENT_TIMESTAMP(),INTERVAL 15 MINUTE), CURDATE(), NULL),
@ -2184,3 +2179,68 @@ INSERT INTO `vn`.`rate`(`dated`, `warehouseFk`, `rate0`, `rate1`, `rate2`, `rate
VALUES VALUES
(DATE_ADD(CURDATE(), INTERVAL -1 YEAR), 1, 10, 15, 20, 25), (DATE_ADD(CURDATE(), INTERVAL -1 YEAR), 1, 10, 15, 20, 25),
(CURDATE(), 1, 12, 17, 22, 27); (CURDATE(), 1, 12, 17, 22, 27);
INSERT INTO `vn`.`awb` (id, code, package, weight, created, amount, transitoryFk, taxFk)
VALUES
(1, '07546501420', 67, 671, CURDATE(), 1761, 1, 1),
(2, '07546491421', 252, 2769, CURDATE(), 5231, 1, 1),
(3, '07546500823', 102, 1495, CURDATE(), 3221, 1, 1),
(4, '99610288821', 252, 2777, CURDATE(), 3641, 1, 1),
(5, '07546500834', 229, 3292, CURDATE(), 6601, 2, 1),
(6, '22101929561', 37, 458, CURDATE(), 441, 2, 1),
(7, '07546491432', 258, 3034, CURDATE(), 6441, 2, 1),
(8, '99610288644', 476, 4461, CURDATE(), 5751, 442, 1),
(9, '99610289193', 302, 2972, CURDATE(), 3871, 442, 1),
(10, '07546500856', 185, 2364, CURDATE(), 5321, 442, 1);
REPLACE INTO vn.dua (id, code, awbFk, issued, operated, booked, bookEntried, gestdocFk, customsValue, companyFk)
VALUES
(1, '19ES0028013A481523', 1, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 1, 11276.95, 442),
(2, '21ES00280136115760', 2, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 1376.20, 442),
(3, '19ES00280131956004', 3, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 3, 14268.50, 442),
(4, '19ES00280131955995', 4, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 1, 8242.50, 442),
(5, '19ES00280132022070', 5, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 10012.49, 442),
(6, '19ES00280132032308', 6, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 19914.25, 442),
(7, '19ES00280132025489', 7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 1934.06, 442),
(8, '19ES00280132025489', 8, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 3618.52, 442),
(9, '19ES00280132025489', 9, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 7126.23, 442),
(10, '19ES00280132025489', 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 4631.45, 442);
REPLACE INTO `vn`.`invoiceIn`(`id`, `serialNumber`,`serial`, `supplierFk`, `issued`, `created`, `supplierRef`, `isBooked`, `companyFk`, `docFk`)
VALUES
(1, 1001, 'R', 1, CURDATE(), CURDATE(), 1234, 0, 442, 1),
(2, 1002, 'R', 1, CURDATE(), CURDATE(), 1235, 1, 442, 1),
(3, 1003, 'R', 1, CURDATE(), CURDATE(), 1236, 0, 442, 1),
(4, 1004, 'R', 1, CURDATE(), CURDATE(), 1237, 0, 442, 1),
(5, 1005, 'R', 1, CURDATE(), CURDATE(), 1238, 1, 442, 1),
(6, 1006, 'R', 2, CURDATE(), CURDATE(), 1239, 0, 442, 1),
(7, 1007, 'R', 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1240, 1, 442, 1),
(8, 1008, 'R', 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1241, 1, 442, 1),
(9, 1009, 'R', 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1242, 1, 442, 1),
(10, 1010, 'R', 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1243, 1, 442, 1);
INSERT INTO `vn`.`invoiceInDueDay`(`invoiceInFk`, `dueDated`, `bankFk`, `amount`)
VALUES
(1, CURDATE(), 1, 237),
(1, CURDATE(), 1, 15.25),
(2, CURDATE(), 1, 168),
(2, CURDATE(), 1, 55.17),
(3, CURDATE(), 1, 87.95),
(3, CURDATE(), 1, 7.65),
(4, CURDATE(), 1, 373.27),
(4, CURDATE(), 1, 73.36),
(5, CURDATE(), 1, 64.23),
(6, CURDATE(), 1, 32.95),
(7, CURDATE(), 1, 58.64);
INSERT INTO `vn`.`duaInvoiceIn`(`id`, `duaFk`, `invoiceInFk`)
VALUES
(1, 1, 1),
(2, 2, 2),
(3, 3, 3),
(4, 4, 4),
(5, 5, 5),
(6, 6, 6),
(7, 7, 7),
(8, 8, 8),
(9, 9, 9),
(10, 10, 10);

File diff suppressed because it is too large Load Diff

View File

@ -39,9 +39,12 @@ TABLES=(
vn vn
alertLevel alertLevel
bookingPlanner bookingPlanner
cplusInvoiceType472
cplusInvoiceType477 cplusInvoiceType477
cplusRectificationType
cplusSubjectOp cplusSubjectOp
cplusTaxBreak cplusTaxBreak
cplusTrascendency472
pgc pgc
time time
claimResponsible claimResponsible
@ -54,6 +57,7 @@ TABLES=(
department department
component component
componentType componentType
continent
) )
dump_tables ${TABLES[@]} dump_tables ${TABLES[@]}

View File

@ -31,7 +31,6 @@ IGNORETABLES=(
--ignore-table=vn.agencyModeZone --ignore-table=vn.agencyModeZone
--ignore-table=vn.agencyProvince --ignore-table=vn.agencyProvince
--ignore-table=vn.agencyWarehouse --ignore-table=vn.agencyWarehouse
--ignore-table=vn.awb
--ignore-table=vn.botanicExport__ --ignore-table=vn.botanicExport__
--ignore-table=vn.clientDefaultCompany --ignore-table=vn.clientDefaultCompany
--ignore-table=vn.color --ignore-table=vn.color
@ -39,6 +38,7 @@ IGNORETABLES=(
--ignore-table=vn.comparativeFilter --ignore-table=vn.comparativeFilter
--ignore-table=vn.coolerPath --ignore-table=vn.coolerPath
--ignore-table=vn.coolerPathDetail --ignore-table=vn.coolerPathDetail
--ignore-table=vn.config__
--ignore-table=vn.department__ --ignore-table=vn.department__
--ignore-table=vn.doc --ignore-table=vn.doc
--ignore-table=vn.entity --ignore-table=vn.entity
@ -49,13 +49,8 @@ IGNORETABLES=(
--ignore-table=vn.grant --ignore-table=vn.grant
--ignore-table=vn.grantGroup --ignore-table=vn.grantGroup
--ignore-table=vn.invoiceCorrection__ --ignore-table=vn.invoiceCorrection__
--ignore-table=vn.invoiceIn
--ignore-table=vn.invoiceInAwb
--ignore-table=vn.invoiceInDueDay
--ignore-table=vn.invoiceInEntry
--ignore-table=vn.invoiceInIntrastat
--ignore-table=vn.invoiceInTax
--ignore-table=vn.itemTaxCountrySpain --ignore-table=vn.itemTaxCountrySpain
--ignore-table=vn.itemFreeNumber__
--ignore-table=vn.mail__ --ignore-table=vn.mail__
--ignore-table=vn.manaSpellers --ignore-table=vn.manaSpellers
--ignore-table=vn.outgoingInvoiceKk --ignore-table=vn.outgoingInvoiceKk
@ -69,7 +64,6 @@ IGNORETABLES=(
--ignore-table=vn.printingQueue --ignore-table=vn.printingQueue
--ignore-table=vn.printServerQueue__ --ignore-table=vn.printServerQueue__
--ignore-table=vn.promissoryNote --ignore-table=vn.promissoryNote
--ignore-table=vn.rate
--ignore-table=vn.referenceRate__ --ignore-table=vn.referenceRate__
--ignore-table=vn.routesControl --ignore-table=vn.routesControl
--ignore-table=vn.salesToPrePrepare --ignore-table=vn.salesToPrePrepare
@ -78,6 +72,7 @@ IGNORETABLES=(
--ignore-table=vn.ticketeToPreparePrepared --ignore-table=vn.ticketeToPreparePrepared
--ignore-table=vn.ticketObservation__ --ignore-table=vn.ticketObservation__
--ignore-table=vn.ticketRequest__ --ignore-table=vn.ticketRequest__
--ignore-table=vn.ticket_print__
--ignore-table=vn.ticketToPrepare --ignore-table=vn.ticketToPrepare
--ignore-table=vn.till__ --ignore-table=vn.till__
--ignore-table=vn.travelThermograph__ --ignore-table=vn.travelThermograph__

View File

@ -23,6 +23,11 @@ export default {
acceptButton: '.vn-confirm.shown button[response=accept]', acceptButton: '.vn-confirm.shown button[response=accept]',
searchButton: 'vn-searchbar vn-icon[icon="search"]' searchButton: 'vn-searchbar vn-icon[icon="search"]'
}, },
moduleIndex: {
anyStarredModule: 'vn-home > div:nth-child(1) > div.modules > a',
firstModulePinIcon: 'vn-home a:nth-child(1) vn-icon[icon="push_pin"]',
firstModuleRemovePinIcon: 'vn-home a:nth-child(1) vn-icon[icon="remove_circle"]'
},
clientsIndex: { clientsIndex: {
createClientButton: `vn-float-button` createClientButton: `vn-float-button`
}, },
@ -316,7 +321,7 @@ export default {
fourthRelevancy: 'vn-item-tags vn-horizontal:nth-child(4) [ng-model="itemTag.priority"]', fourthRelevancy: 'vn-item-tags vn-horizontal:nth-child(4) [ng-model="itemTag.priority"]',
fourthRemoveTagButton: 'vn-item-tags vn-horizontal:nth-child(4) vn-icon-button[icon="delete"]', fourthRemoveTagButton: 'vn-item-tags vn-horizontal:nth-child(4) vn-icon-button[icon="delete"]',
fifthTag: 'vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[ng-model="itemTag.tagFk"]', fifthTag: 'vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[ng-model="itemTag.tagFk"]',
fifthValue: 'vn-item-tags vn-horizontal:nth-child(5) vn-textfield[ng-model="itemTag.value"]', fifthValue: 'vn-item-tags vn-horizontal:nth-child(5) vn-autocomplete[ng-model="itemTag.value"]',
fifthRelevancy: 'vn-item-tags vn-horizontal:nth-child(5) vn-input-number[ng-model="itemTag.priority"]', fifthRelevancy: 'vn-item-tags vn-horizontal:nth-child(5) vn-input-number[ng-model="itemTag.priority"]',
sixthTag: 'vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[ng-model="itemTag.tagFk"]', sixthTag: 'vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[ng-model="itemTag.tagFk"]',
sixthValue: 'vn-item-tags vn-horizontal:nth-child(6) vn-textfield[ng-model="itemTag.value"]', sixthValue: 'vn-item-tags vn-horizontal:nth-child(6) vn-textfield[ng-model="itemTag.value"]',

View File

@ -0,0 +1,43 @@
import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer';
describe('Starred modules path', async() => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.login('employee');
});
afterAll(async() => {
await browser.close();
});
it('should make sure there are no modules pinned yet', async() => {
const count = await page.countElement(selectors.moduleIndex.anyStarredModule);
expect(count).toEqual(0);
});
it('should set a module as favore', async() => {
await page.waitToClick(selectors.moduleIndex.firstModulePinIcon);
const message = await page.waitForSnackbar();
const count = await page.countElement(selectors.moduleIndex.anyStarredModule);
expect(message.text).toContain('Data saved!');
expect(count).toEqual(1);
});
it('should remove the module from favores', async() => {
await page.waitToClick(selectors.moduleIndex.firstModuleRemovePinIcon);
const message = await page.waitForSnackbar();
const count = await page.countElement(selectors.moduleIndex.anyStarredModule);
expect(message.text).toContain('Data saved!');
expect(count).toEqual(0);
});
});

View File

@ -47,6 +47,7 @@ describe('Client balance path', () => {
await page.closePopup(); await page.closePopup();
await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.waitToClick(selectors.clientBalance.newPaymentButton);
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash');
await page.clearInput(selectors.clientBalance.newDescription);
await page.write(selectors.clientBalance.newDescription, 'Description'); await page.write(selectors.clientBalance.newDescription, 'Description');
await page.waitToClick(selectors.clientBalance.saveButton); await page.waitToClick(selectors.clientBalance.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
@ -86,6 +87,7 @@ describe('Client balance path', () => {
await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.waitToClick(selectors.clientBalance.newPaymentButton);
await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); await page.write(selectors.clientBalance.newPaymentAmount, amountPaid);
await page.clearInput(selectors.clientBalance.newDescription);
await page.write(selectors.clientBalance.newDescription, 'Payment'); await page.write(selectors.clientBalance.newDescription, 'Payment');
await page.write(selectors.clientBalance.deliveredAmount, cashHanded); await page.write(selectors.clientBalance.deliveredAmount, cashHanded);
const refund = await page.waitToGetProperty(selectors.clientBalance.refundAmount, 'value'); const refund = await page.waitToGetProperty(selectors.clientBalance.refundAmount, 'value');
@ -107,6 +109,7 @@ describe('Client balance path', () => {
await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.waitToClick(selectors.clientBalance.newPaymentButton);
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt'); await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt');
await page.overwrite(selectors.clientBalance.newPaymentAmount, '-150'); await page.overwrite(selectors.clientBalance.newPaymentAmount, '-150');
await page.clearInput(selectors.clientBalance.newDescription);
await page.write(selectors.clientBalance.newDescription, 'Description'); await page.write(selectors.clientBalance.newDescription, 'Description');
await page.waitToClick(selectors.clientBalance.saveButton); await page.waitToClick(selectors.clientBalance.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();

View File

@ -16,7 +16,7 @@ describe('Item create tags path', () => {
await browser.close(); await browser.close();
}); });
it(`should create a new tag and delete a former one`, async() => { it('should create a new tag and delete a former one', async() => {
await page.waitToClick(selectors.itemTags.fourthRemoveTagButton); await page.waitToClick(selectors.itemTags.fourthRemoveTagButton);
await page.waitToClick(selectors.itemTags.addItemTagButton); await page.waitToClick(selectors.itemTags.addItemTagButton);
await page.autocompleteSearch(selectors.itemTags.seventhTag, 'Ancho de la base'); await page.autocompleteSearch(selectors.itemTags.seventhTag, 'Ancho de la base');
@ -29,7 +29,7 @@ describe('Item create tags path', () => {
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');
}); });
it(`should confirm the fourth row data is the expected one`, async() => { it('should confirm the fourth row data is the expected one', async() => {
await page.reloadSection('item.card.tags'); await page.reloadSection('item.card.tags');
await page.waitForSelector('vn-item-tags'); await page.waitForSelector('vn-item-tags');
let result = await page.waitToGetProperty(selectors.itemTags.fourthTag, 'value'); let result = await page.waitToGetProperty(selectors.itemTags.fourthTag, 'value');
@ -47,7 +47,7 @@ describe('Item create tags path', () => {
expect(result).toEqual('4'); expect(result).toEqual('4');
}); });
it(`should confirm the fifth row data is the expected one`, async() => { it('should confirm the fifth row data is the expected one', async() => {
let tag = await page let tag = await page
.waitToGetProperty(selectors.itemTags.fifthTag, 'value'); .waitToGetProperty(selectors.itemTags.fifthTag, 'value');
@ -62,7 +62,7 @@ describe('Item create tags path', () => {
expect(relevancy).toEqual('5'); expect(relevancy).toEqual('5');
}); });
it(`should confirm the sixth row data is the expected one`, async() => { it('should confirm the sixth row data is the expected one', async() => {
let tag = await page let tag = await page
.waitToGetProperty(selectors.itemTags.sixthTag, 'value'); .waitToGetProperty(selectors.itemTags.sixthTag, 'value');

View File

@ -29,7 +29,7 @@ export default class Contextmenu {
if (!event.defaultPrevented) if (!event.defaultPrevented)
event.preventDefault(); event.preventDefault();
if (!this.isFilterEnabled()) return; if (!this.isMenuEnabled()) return;
const parent = this.$.contextmenu; const parent = this.$.contextmenu;
parent.style.top = event.pageY + 'px'; parent.style.top = event.pageY + 'px';
@ -121,13 +121,31 @@ export default class Contextmenu {
return isEnabled != 'false'; return isEnabled != 'false';
} }
isMenuEnabled() {
if (!this.rowHeader) return true;
const isEnabled = this.rowHeader.getAttribute('menu-enabled');
return isEnabled != 'false';
}
/** /**
* Returns true if filter * Returns true if filter
* by selection is allowed * by selection is enabled and
* the menu can be interacted
* *
* @return {Boolean} * @return {Boolean}
*/ */
isFilterAllowed() { isFilterAllowed() {
return this.isActionAllowed() && this.isFilterEnabled();
}
/**
* Returns true if the
* context menu can be interacted
*
* @return {Boolean}
*/
isActionAllowed() {
if (!this.target) return false; if (!this.target) return false;
const isTableCell = this.target.closest('vn-td, .vn-td'); const isTableCell = this.target.closest('vn-td, .vn-td');
@ -179,9 +197,13 @@ export default class Contextmenu {
if (!where) return; if (!where) return;
const whereKeys = Object.keys(where); const whereKeys = Object.keys(where);
for (let key of whereKeys) for (let key of whereKeys) {
removeProp(where, filterKey, key); removeProp(where, filterKey, key);
if (!Object.keys(where))
delete userFilter.where;
}
function removeProp(instance, findProp, prop) { function removeProp(instance, findProp, prop) {
if (prop == findProp) if (prop == findProp)
delete instance[prop]; delete instance[prop];
@ -208,6 +230,16 @@ export default class Contextmenu {
const userParams = this.model.userParams; const userParams = this.model.userParams;
this.model.applyFilter(null, userParams); this.model.applyFilter(null, userParams);
} }
/**
* Copies the current field
* value to the clipboard
*/
copyValue() {
const cell = angular.element(this.cell);
if (navigator && navigator.clipboard)
navigator.clipboard.writeText(cell.text());
}
} }
Contextmenu.$inject = ['$element', '$scope', '$transclude']; Contextmenu.$inject = ['$element', '$scope', '$transclude'];

View File

@ -174,4 +174,9 @@ vn-table {
.vn-check { .vn-check {
margin: 0; margin: 0;
} }
.empty-rows {
color: $color-font-secondary;
font-size: 1.375rem;
text-align: center;
}
} }

View File

@ -16,6 +16,7 @@ export default function moduleImport(moduleName) {
case 'travel' : return import('travel/front'); case 'travel' : return import('travel/front');
case 'worker' : return import('worker/front'); case 'worker' : return import('worker/front');
case 'invoiceOut' : return import('invoiceOut/front'); case 'invoiceOut' : return import('invoiceOut/front');
case 'invoiceIn' : return import('invoiceIn/front');
case 'route' : return import('route/front'); case 'route' : return import('route/front');
case 'entry' : return import('entry/front'); case 'entry' : return import('entry/front');
case 'account' : return import('account/front'); case 'account' : return import('account/front');

View File

@ -0,0 +1,40 @@
<vn-dialog class="edit"
vn-id="bankEntityDialog"
on-open="$ctrl.resetData()"
on-accept="$ctrl.onAccept()"
message="New bank entity">
<tpl-body>
<p translate>Please, ensure you put the correct data!</p>
<vn-horizontal>
<vn-textfield
vn-one
vn-focus
vn-id="entityName"
label="Name"
ng-model="$ctrl.data.name"
required="true">
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield
vn-one
vn-focus
vn-id="bic"
label="Swift"
ng-model="$ctrl.data.bic"
required="true">
</vn-textfield>
<vn-autocomplete vn-one
ng-model="$ctrl.data.countryFk"
url="Countries"
show-field="country"
value-field="id"
label="Country">
</vn-autocomplete>
</vn-horizontal>
</tpl-body>
<tpl-buttons>
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
<button id= "saveBankEntity" response="accept" translate>Save</button>
</tpl-buttons>
</vn-dialog>

View File

@ -0,0 +1,37 @@
import ngModule from '../../module';
import Component from 'core/lib/component';
import './style.scss';
class Controller extends Component {
open() {
this.$.bankEntityDialog.show();
}
resetData() {
this.data = {};
}
onAccept() {
try {
if (!this.data.countryFk)
throw new Error(`The country can't be empty`);
this.$http.post(`bankEntities`, this.data).then(res => {
this.vnApp.showMessage(this.$t('The bank entity has been created. You can save the data now'));
this.emit('response', {$response: res.data});
});
} catch (e) {
this.vnApp.showError(this.$t(e.message));
return false;
}
return true;
}
}
ngModule.vnComponent('vnNewBankEntity', {
template: require('./index.html'),
controller: Controller,
bindings: {
data: '<',
}
});

View File

@ -0,0 +1,53 @@
import './index';
describe('Salix Component vnNewBankEntity', () => {
let controller;
let $httpBackend;
let $scope;
let $element;
let vnApp;
beforeEach(ngModule('salix'));
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _vnApp_) => {
$httpBackend = _$httpBackend_;
vnApp = _vnApp_;
jest.spyOn(vnApp, 'showError');
$scope = $rootScope.$new();
$element = angular.element('<vn-dialog></dialog>');
controller = $componentController('vnNewBankEntity', {$element, $scope});
}));
describe('resetData()', () => {
it('should reset the location in the controller', () => {
expect(controller.data).toBeUndefined();
controller.resetData();
expect(controller.data).toEqual({});
});
});
describe('onAccept()', () => {
it('should throw an error if there is no country id in the location', () => {
jest.spyOn(controller.vnApp, 'showMessage');
controller.data = {};
controller.onAccept();
expect(controller.vnApp.showError).toHaveBeenCalledWith(`The country can't be empty`);
});
it('should do add the new bank entity', () => {
controller.data = {
countryFk: 1
};
$httpBackend.expectPOST('bankEntities', controller.data).respond(200, controller.data);
controller.onAccept();
$httpBackend.flush();
});
});
});

View File

@ -0,0 +1,12 @@
New postcode: Nuevo código postal
New city: Nueva ciudad
New province: Nueva provincia
Please, ensure you put the correct data!: ¡Por favor, asegúrate de poner los datos correctos!
The postcode can't be empty: El código postal no puede quedar vacío
The town can't be empty: La población no puede quedar vacía
The province can't be empty: La provincia no puede quedar vacía
The country can't be empty: El país no puede quedar vacío
The postcode has been created. You can save the data now: Se ha creado el código postal. Ahora puedes guardar los datos
The city has been created: Se ha creado la ciudad
The province has been created: Se ha creado la provincia
The bank entity has been created. You can save the data now: Se ha creado la entidad bancaria. Puedes guardar los datos ahora

View File

@ -0,0 +1,9 @@
@import "variables";
vn-new-bank-entity {
vn-dialog {
p {
color: $color-alert
}
}
}

View File

@ -1,10 +1,57 @@
<div> <div>
<div class="top-border">
<span translate>Favorites</span>
</div>
<div
ng-if="!$ctrl.starredCount"
class="starred-info vn-py-md">
<span translate class="empty">You can set modules as favorites by clicking their icon</span>
<vn-icon icon="push_pin"></vn-icon>
</div>
<div class="modules"> <div class="modules">
<a <a
ng-repeat="mod in ::$ctrl.modules" ng-repeat="mod in ::$ctrl.modules"
ng-if='mod.starred'
ui-sref="{{::mod.route.state}}" ui-sref="{{::mod.route.state}}"
translate-attr="{title: mod.name}" translate-attr="{title: mod.name}"
class="vn-shadow"> class="vn-shadow">
<div
vn-tooltip="Remove from favorites"
class="pin"
ng-click="$ctrl.toggleStarredModule(mod, $event)">
<vn-icon icon="remove_circle"></vn-icon>
</div>
<div>
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
</div>
<h4 ng-bind-html="$ctrl.getModuleName(mod)"></h4>
<span
ng-show="::mod.keyBind"
vn-tooltip="Ctrl + Alt + {{::mod.keyBind}}">
({{::mod.keyBind}})
</span>
<span ng-show="::!mod.keyBind">&nbsp;</span>
</a>
</div>
</div>
<div>
<div
class="top-border"
ng-if="$ctrl.regularCount > 0 && $ctrl.starredCount > 0">
</div>
<div class="modules">
<a
ng-repeat="mod in ::$ctrl.modules"
ng-if='!mod.starred'
ui-sref="{{::mod.route.state}}"
translate-attr="{title: mod.name}"
class="vn-shadow">
<div
vn-tooltip="Add to favorites"
class="pin"
ng-click="$ctrl.toggleStarredModule(mod, $event)">
<vn-icon icon="push_pin"></vn-icon>
</div>
<div> <div>
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon> <vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
</div> </div>

View File

@ -9,6 +9,55 @@ export default class Controller extends Component {
this.$sce = $sce; this.$sce = $sce;
} }
get modules() {
return this._modules;
}
set modules(value) {
this._modules = value;
this.getStarredModules();
}
countModules() {
this.starredCount = 0;
this.regularCount = 0;
this.modules.forEach(module => {
if (module.starred) this.starredCount ++;
else this.regularCount ++;
});
}
getStarredModules() {
this.$http.get('starredModules/getStarredModules')
.then(res => {
if (!res.data.length) return;
for (let starredModule of res.data) {
const module = this.modules.find(mod => mod.name === starredModule.moduleFk);
module.starred = true;
}
this.countModules();
});
}
toggleStarredModule(module, event) {
if (event.defaultPrevented) return;
event.preventDefault();
event.stopPropagation();
const params = {moduleName: module.name};
const query = `starredModules/toggleStarredModule`;
this.$http.post(query, params).then(res => {
if (res.data)
module.starred = true;
else
module.starred = false;
this.vnApp.showSuccess(this.$t('Data saved!'));
this.countModules();
});
}
getModuleName(mod) { getModuleName(mod) {
let getName = mod => { let getName = mod => {
let name = this.$t(mod.name); let name = this.$t(mod.name);

View File

@ -0,0 +1,75 @@
import './home';
describe('Salix Component vnHome', () => {
let controller;
let $httpBackend;
let $scope;
let $element;
beforeEach(ngModule('salix'));
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _vnApp_, $window) => {
$httpBackend = _$httpBackend_;
$scope = $rootScope.$new();
$element = angular.element('<vn-home></vn-home>');
$window.routes = [{module: 'client', name: 'Clients'}];
controller = $componentController('vnHome', {$element, $scope, $window});
}));
describe('getStarredModules()', () => {
it('should not set any of the modules as starred if there are no starred modules for the user', () => {
const expectedResponse = [];
controller._modules = [{module: 'client', name: 'Clients'}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse);
$httpBackend.expectGET('starredModules/getStarredModules').respond(expectedResponse);
controller.getStarredModules();
$httpBackend.flush();
expect(controller._modules.length).toEqual(1);
expect(controller._modules[0].starred).toBeUndefined();
});
it('should set the example module as starred since its the starred module for the user', () => {
const expectedResponse = [{id: 1, moduleFk: 'Clients', workerFk: 9}];
controller._modules = [{module: 'client', name: 'Clients'}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse);
$httpBackend.expectGET('starredModules/getStarredModules').respond(expectedResponse);
controller.getStarredModules();
$httpBackend.flush();
expect(controller._modules.length).toEqual(1);
expect(controller._modules[0].starred).toBe(true);
});
});
describe('toggleStarredModule()', () => {
it(`should set the received module as starred if it wasn't starred`, () => {
const expectedResponse = [{id: 1, moduleFk: 'Clients', workerFk: 9}];
const event = new Event('target');
controller._modules = [{module: 'client', name: 'Clients'}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(expectedResponse);
$httpBackend.expectPOST('starredModules/toggleStarredModule').respond(expectedResponse);
controller.toggleStarredModule(controller._modules[0], event);
$httpBackend.flush();
expect(controller._modules.length).toEqual(1);
expect(controller._modules[0].starred).toBe(true);
});
it(`should set the received module as regular if it was starred`, () => {
const event = new Event('target');
controller._modules = [{module: 'client', name: 'Clients', starred: true}];
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond([]);
$httpBackend.expectPOST('starredModules/toggleStarredModule').respond(undefined);
controller.toggleStarredModule(controller._modules[0], event);
$httpBackend.flush();
expect(controller._modules.length).toEqual(1);
expect(controller._modules[0].starred).toBe(false);
});
});
});

View File

@ -0,0 +1,4 @@
Favorites: Favoritos
You can set modules as favorites by clicking their icon: Puedes establecer módulos como favoritos haciendo clic en el icono
Add to favorites: Añadir a favoritos.
Remove from favorites: Quitar de favoritos.

View File

@ -10,28 +10,76 @@ vn-home {
text-align: center; text-align: center;
margin-bottom: 15px; margin-bottom: 15px;
} }
& > .modules {
display: flex; & .starred-info{
flex: 1; display: block;
text-align: center;
box-sizing: border-box;
color: $color-font-secondary;
font-size: 1.375rem;
& > .empty {
text-align: center;
box-sizing: border-box;
color: $color-font-secondary;
font-size: 1em;
}
& > vn-icon {
font-size: 1.2rem;
}
}
& > .top-border {
margin: 0 auto;
flex-direction: row; flex-direction: row;
justify-content: center; float: center;
max-width: 690px;
border-bottom: 2px solid $color-font-secondary;
line-height: 2px;
> span {
height: 10px;
margin-left: 30px;
background-color: $color-bg;
padding:0 11px;
}
}
& > .modules {
padding: 10px 0 10px 0;
display: flex;
flex-wrap: wrap; flex-wrap: wrap;
flex: 1;
max-width: 704px; max-width: 704px;
margin: 0 auto; margin: 0 auto;
& > a { & > a {
@extend %clickable-light; @extend %clickable-light;
overflow:hidden;
border-radius: 6px;
background-color: $color-button;
color: $color-font-dark;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow:hidden;
justify-content: center;
border-radius: 6px;
height: 128px; height: 128px;
width: 128px; width: 128px;
margin: 8px; margin: 8px;
padding: 16px; padding: 16px;
justify-content: center; background-color: $color-button;
color: $color-font-dark;
& .pin {
opacity: 0;
flex-direction: row;
justify-content: left;
height: 20px;
width: 20px;
vn-icon {
margin: auto;
font-size: 1.5rem;
}
}
&:hover .pin {
opacity: 1;
}
& > div { & > div {
height: 70px; height: 70px;
@ -56,10 +104,6 @@ vn-home {
color: inherit; color: inherit;
margin: 0; margin: 0;
line-height: 24px; line-height: 24px;
/* & > .bind-letter {
color: #FD0;
} */
} }
} }
} }

View File

@ -14,3 +14,4 @@ import './summary';
import './topbar/topbar'; import './topbar/topbar';
import './user-popover'; import './user-popover';
import './upload-photo'; import './upload-photo';
import './bank-entity';

View File

@ -43,6 +43,7 @@ Workers: Trabajadores
Routes: Rutas Routes: Rutas
Locator: Localizador Locator: Localizador
Invoices out: Facturas emitidas Invoices out: Facturas emitidas
Invoices in: Fact. recibidas
Entries: Entradas Entries: Entradas
Users: Usuarios Users: Usuarios
Suppliers: Proveedores Suppliers: Proveedores

View File

@ -6,6 +6,7 @@ import './modules/zone/front/module.js';
import './modules/claim/front/module.js'; import './modules/claim/front/module.js';
import './modules/client/front/module.js'; import './modules/client/front/module.js';
import './modules/invoiceOut/front/module.js'; import './modules/invoiceOut/front/module.js';
import './modules/invoiceIn/front/module.js';
import './modules/item/front/module.js'; import './modules/item/front/module.js';
import './modules/order/front/module.js'; import './modules/order/front/module.js';
import './modules/route/front/module.js'; import './modules/route/front/module.js';

View File

@ -91,5 +91,6 @@
"The observation type can't be repeated": "The observation type can't be repeated", "The observation type can't be repeated": "The observation type can't be repeated",
"New ticket request has been created with price": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}* and a price of *{{price}} €*", "New ticket request has been created with price": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}* and a price of *{{price}} €*",
"New ticket request has been created": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}*", "New ticket request has been created": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}*",
"There's a new urgent ticket": "There's a new urgent ticket: [{{title}}](https://cau.verdnatura.es/WorkOrder.do?woMode=viewWO&woID={{issueId}})" "There's a new urgent ticket": "There's a new urgent ticket: [{{title}}](https://cau.verdnatura.es/WorkOrder.do?woMode=viewWO&woID={{issueId}})",
"Swift / BIC cannot be empty": "Swift / BIC cannot be empty"
} }

View File

@ -167,9 +167,12 @@
"You can't upload images on the test environment": "No puedes subir imágenes en el entorno de pruebas", "You can't upload images on the test environment": "No puedes subir imágenes en el entorno de pruebas",
"The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta", "The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta",
"Sorts whole route": "Reordena ruta entera", "Sorts whole route": "Reordena ruta entera",
"Invalid account": "Cuenta inválida", "New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día <strong>{{shipped}}</strong>, con una cantidad de <strong>{{quantity}}</strong> y un precio de <strong>{{price}} €</strong>",
"New ticket request has been created with price": "Se ha creado una nueva petición de compra *'{{description}}'* para el día *{{shipped}}*, con una cantidad de *{{quantity}}* y un precio de *{{price}} €*", "New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día <strong>{{shipped}}</strong>, con una cantidad de <strong>{{quantity}}</strong>",
"New ticket request has been created": "Se ha creado una nueva petición de compra *'{{description}}'* para el día *{{shipped}}*, con una cantidad de *{{quantity}}*", "Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío",
"This BIC already exist.": "Este BIC ya existe.",
"That item doesn't exists": "Ese artículo no existe", "That item doesn't exists": "Ese artículo no existe",
"There's a new urgent ticket": "Hay un nuevo ticket urgente: [{{title}}](https://cau.verdnatura.es/WorkOrder.do?woMode=viewWO&woID={{issueId}})" "There's a new urgent ticket": "Hay un nuevo ticket urgente: [{{title}}](https://cau.verdnatura.es/WorkOrder.do?woMode=viewWO&woID={{issueId}})",
"Invalid account": "Cuenta inválida",
"Compensation account is empty": "La cuenta para compensar está vacia"
} }

View File

@ -62,7 +62,10 @@ module.exports = function(Self) {
const bank = await models.Bank.findById(args.bankFk); const bank = await models.Bank.findById(args.bankFk);
const accountingType = await models.AccountingType.findById(bank.accountingTypeFk); const accountingType = await models.AccountingType.findById(bank.accountingTypeFk);
if (args.compensationAccount) { if (accountingType.code == 'compensation') {
if (!args.compensationAccount)
throw new UserError('Compensation account is empty');
const supplierCompensation = await models.Supplier.findOne({ const supplierCompensation = await models.Supplier.findOne({
where: { where: {
account: args.compensationAccount account: args.compensationAccount
@ -92,12 +95,11 @@ module.exports = function(Self) {
], ],
options); options);
} else { } else {
const description = `${clientOriginal.id} : ${clientOriginal.nickname} - ${accountingType.receiptDescription}`; const description = `${clientOriginal.id} : ${clientOriginal.socialName} - ${accountingType.receiptDescription}`;
const [xdiarioNew] = await Self.rawSql( const [xdiarioNew] = await Self.rawSql(
`SELECT xdiario_new(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ledger;`, `SELECT xdiario_new(?, CURDATE(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ledger;`,
[ [
null, null,
Date(),
bank.account, bank.account,
clientOriginal.accountingAccount, clientOriginal.accountingAccount,
description, description,
@ -114,10 +116,9 @@ module.exports = function(Self) {
options); options);
await Self.rawSql( await Self.rawSql(
`SELECT xdiario_new(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`, `SELECT xdiario_new(?, CURDATE(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`,
[ [
xdiarioNew.ledger, xdiarioNew.ledger,
Date(),
clientOriginal.accountingAccount, clientOriginal.accountingAccount,
bank.account, bank.account,
description, description,

View File

@ -26,12 +26,22 @@ module.exports = Self => {
Self.lastActiveTickets = async(id, ticketId) => { Self.lastActiveTickets = async(id, ticketId) => {
const ticket = await Self.app.models.Ticket.findById(ticketId); const ticket = await Self.app.models.Ticket.findById(ticketId);
const query = ` const query = `
SELECT t.id, t.shipped, a.name AS agencyName, w.name AS warehouseName, ad.city AS address SELECT
FROM vn.ticket t t.id,
t.shipped,
a.name AS agencyName,
w.name AS warehouseName,
ad.nickname AS nickname,
ad.city AS city,
ad.postalCode AS postalCode,
ad.street AS street,
pr.name AS name
FROM ticket t
JOIN vn.ticketState ts ON t.id = ts.ticketFk JOIN vn.ticketState ts ON t.id = ts.ticketFk
JOIN vn.agencyMode a ON t.agencyModeFk = a.id JOIN vn.agencyMode a ON t.agencyModeFk = a.id
JOIN vn.warehouse w ON t.warehouseFk = w.id JOIN vn.warehouse w ON t.warehouseFk = w.id
JOIN vn.address ad ON t.addressFk = ad.id JOIN vn.address ad ON t.addressFk = ad.id
JOIN vn.province pr ON ad.provinceFk = pr.id
WHERE t.shipped >= CURDATE() AND t.clientFk = ? AND ts.alertLevel = 0 WHERE t.shipped >= CURDATE() AND t.clientFk = ? AND ts.alertLevel = 0
AND t.id <> ? AND t.warehouseFk = ? AND t.id <> ? AND t.warehouseFk = ?
ORDER BY t.shipped ORDER BY t.shipped

View File

@ -1,4 +1,5 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');
describe('Client createReceipt', () => { describe('Client createReceipt', () => {
const clientFk = 108; const clientFk = 108;
@ -6,18 +7,34 @@ describe('Client createReceipt', () => {
const companyFk = 442; const companyFk = 442;
const amountPaid = 12.50; const amountPaid = 12.50;
const description = 'Receipt description'; const description = 'Receipt description';
const activeCtx = {
accessToken: {userId: 5},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
const ctx = {req: activeCtx};
activeCtx.http.req.__ = value => {
return value;
};
beforeEach(() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
});
it('should create a new receipt', async() => { it('should create a new receipt', async() => {
const bankFk = 1; const bankFk = 1;
let ctx = { ctx.args = {
args: {
clientFk: clientFk, clientFk: clientFk,
payed: payed, payed: payed,
companyFk: companyFk, companyFk: companyFk,
bankFk: bankFk, bankFk: bankFk,
amountPaid: amountPaid, amountPaid: amountPaid,
description: description description: description
}
}; };
const receipt = await app.models.Client.createReceipt(ctx); const receipt = await app.models.Client.createReceipt(ctx);
@ -38,11 +55,32 @@ describe('Client createReceipt', () => {
await till.destroy(); await till.destroy();
}); });
it('should throw Compensation account is empty', async() => {
const bankFk = 3;
ctx.args = {
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description
};
try {
await app.models.Client.createReceipt(ctx);
} catch (e) {
error = e;
}
expect(error).toBeDefined();
expect(error.message).toEqual('Compensation account is empty');
});
it('should throw Invalid account if compensationAccount does not belongs to a client nor a supplier', async() => { it('should throw Invalid account if compensationAccount does not belongs to a client nor a supplier', async() => {
let error; let error;
const bankFk = 3; const bankFk = 3;
const ctx = { ctx.args = {
args: {
clientFk: clientFk, clientFk: clientFk,
payed: payed, payed: payed,
companyFk: companyFk, companyFk: companyFk,
@ -50,7 +88,6 @@ describe('Client createReceipt', () => {
amountPaid: amountPaid, amountPaid: amountPaid,
description: description, description: description,
compensationAccount: 'non existing account' compensationAccount: 'non existing account'
}
}; };
try { try {
@ -65,8 +102,8 @@ describe('Client createReceipt', () => {
it('should create a new receipt with a compensation for a client', async() => { it('should create a new receipt with a compensation for a client', async() => {
const bankFk = 3; const bankFk = 3;
const ctx = {
args: { ctx.args = {
clientFk: clientFk, clientFk: clientFk,
payed: payed, payed: payed,
companyFk: companyFk, companyFk: companyFk,
@ -74,7 +111,6 @@ describe('Client createReceipt', () => {
amountPaid: amountPaid, amountPaid: amountPaid,
description: description, description: description,
compensationAccount: '4300000001' compensationAccount: '4300000001'
}
}; };
const receipt = await app.models.Client.createReceipt(ctx); const receipt = await app.models.Client.createReceipt(ctx);
const receiptCompensated = await app.models.Receipt.findOne({ const receiptCompensated = await app.models.Receipt.findOne({
@ -104,16 +140,16 @@ describe('Client createReceipt', () => {
}); });
it('should create a new receipt with a compensation for a supplier', async() => { it('should create a new receipt with a compensation for a supplier', async() => {
const ctx = { const bankFk = 3;
args: {
ctx.args = {
clientFk: clientFk, clientFk: clientFk,
payed: payed, payed: payed,
companyFk: companyFk, companyFk: companyFk,
bankFk: 3, bankFk: bankFk,
amountPaid: amountPaid, amountPaid: amountPaid,
description: description, description: description,
compensationAccount: '4100000001' compensationAccount: '4100000001'
}
}; };
const receipt = await app.models.Client.createReceipt(ctx); const receipt = await app.models.Client.createReceipt(ctx);

View File

@ -0,0 +1,18 @@
const app = require('vn-loopback/server/server');
describe('Client last active tickets', () => {
it('should receive an array of last active tickets of Bruce Wayne', async() => {
const ticketId = 22;
const clientId = 109;
const warehouseId = 5;
const result = await app.models.Client.lastActiveTickets(clientId, ticketId, warehouseId);
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
const properties = Object.keys(anyResult);
expect(properties.length).toEqual(9);
expect(result.length).toEqual(3);
});
});

View File

@ -1,8 +0,0 @@
module.exports = Self => {
Self.validatesPresenceOf('name', {
message: `Name cannot be blank`
});
Self.validatesPresenceOf('bic', {
message: `Swift / BIC can't be empty`
});
};

View File

@ -1,3 +1,5 @@
const LoopBackContext = require('loopback-context');
module.exports = function(Self) { module.exports = function(Self) {
require('../methods/receipt/filter')(Self); require('../methods/receipt/filter')(Self);
@ -23,13 +25,10 @@ module.exports = function(Self) {
Self.observe('before save', async function(ctx) { Self.observe('before save', async function(ctx) {
if (ctx.isNewInstance) { if (ctx.isNewInstance) {
let token = ctx.options.accessToken; const loopBackContext = LoopBackContext.getCurrentContext();
let userId = token && token.userId; ctx.instance.workerFk = loopBackContext.active.accessToken.userId;
ctx.instance.workerFk = userId;
await Self.app.models.Till.create({ await Self.app.models.Till.create({
workerFk: userId, workerFk: ctx.instance.workerFk,
bankFk: ctx.instance.bankFk, bankFk: ctx.instance.bankFk,
in: ctx.instance.amountPaid, in: ctx.instance.amountPaid,
concept: ctx.instance.description, concept: ctx.instance.description,

View File

@ -78,6 +78,8 @@ module.exports = Self => {
return {'ic.id': value}; return {'ic.id': value};
case 'salesPersonFk': case 'salesPersonFk':
return {'it.workerFk': value}; return {'it.workerFk': value};
case 'code':
return {'it.code': value};
case 'typeFk': case 'typeFk':
return {'i.typeFk': value}; return {'i.typeFk': value};
case 'active': case 'active':
@ -103,6 +105,7 @@ module.exports = Self => {
i.id AS itemFk, i.id AS itemFk,
i.size, i.size,
i.density, i.density,
it.code,
i.typeFk, i.typeFk,
i.family, i.family,
i.isActive, i.isActive,

View File

@ -37,8 +37,8 @@
<vn-th field="quantity">Quantity</vn-th> <vn-th field="quantity">Quantity</vn-th>
<vn-th field="description" style="text-align: center">Description</vn-th> <vn-th field="description" style="text-align: center">Description</vn-th>
<vn-th field="size">Size</vn-th> <vn-th field="size">Size</vn-th>
<vn-th field="tags" style="text-align: center">Tags</vn-th> <vn-th field="name" style="text-align: center">Tags</vn-th>
<vn-th field="type">Type</vn-th> <vn-th field="code">Type</vn-th>
<vn-th field="intrastat">Intrastat</vn-th> <vn-th field="intrastat">Intrastat</vn-th>
<vn-th field="origin">Origin</vn-th> <vn-th field="origin">Origin</vn-th>
<vn-th field="density">Density</vn-th> <vn-th field="density">Density</vn-th>
@ -109,7 +109,7 @@
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td shrink title="{{::buy.type}}"> <vn-td shrink title="{{::buy.type}}">
{{::buy.type}} {{::buy.code}}
</vn-td> </vn-td>
<vn-td shrink title="{{::item.intrastat}}"> <vn-td shrink title="{{::item.intrastat}}">
{{::buy.intrastat}} {{::buy.intrastat}}

View File

@ -31,19 +31,19 @@
"state": "entry.index", "state": "entry.index",
"component": "vn-entry-index", "component": "vn-entry-index",
"description": "Entries", "description": "Entries",
"acl": ["buyer"] "acl": ["buyer", "administrative"]
}, { }, {
"url": "/latest-buys?q", "url": "/latest-buys?q",
"state": "entry.latestBuys", "state": "entry.latestBuys",
"component": "vn-entry-latest-buys", "component": "vn-entry-latest-buys",
"description": "Latest buys", "description": "Latest buys",
"acl": ["buyer"] "acl": ["buyer", "administrative"]
}, { }, {
"url": "/create?supplierFk&travelFk&companyFk", "url": "/create?supplierFk&travelFk&companyFk",
"state": "entry.create", "state": "entry.create",
"component": "vn-entry-create", "component": "vn-entry-create",
"description": "New entry", "description": "New entry",
"acl": ["buyer"] "acl": ["buyer", "administrative"]
}, { }, {
"url": "/:id", "url": "/:id",
"state": "entry.card", "state": "entry.card",

View File

@ -0,0 +1,171 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const buildFilter = require('vn-loopback/util/filter').buildFilter;
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
module.exports = Self => {
Self.remoteMethodCtx('filter', {
description: 'Find all instances of the model matched by filter from the data source.',
accessType: 'READ',
accepts: [
{
arg: 'filter',
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'}
},
{
arg: 'search',
type: 'string',
description: 'Searchs the invoiceOut by id',
http: {source: 'query'}
},
{
arg: 'supplierRef',
type: 'string',
description: 'The supplier reference'
},
{
arg: 'fi',
type: 'string',
description: 'The supplier fiscal id'
},
{
arg: 'serialNumber',
type: 'number',
description: 'The serial number'
},
{
arg: 'serial',
type: 'string',
description: 'The serial'
},
{
arg: 'amount',
type: 'number',
description: 'The amount'
},
{
arg: 'from',
type: 'date',
description: `The from date filter`
}, {
arg: 'to',
type: 'date',
description: `The to date filter`
},
{
arg: 'issued',
type: 'date',
description: 'The issued date'
},
{
arg: 'account',
type: 'number',
description: 'The account number'
},
{
arg: 'awbCode',
type: 'string',
description: 'The Air Waybill code'
},
{
arg: 'isBooked',
type: 'boolean',
description: 'Whether the the invoice is booked or not',
},
],
returns: {
type: ['object'],
root: true
},
http: {
path: `/filter`,
verb: 'GET'
}
});
Self.filter = async(ctx, filter) => {
const conn = Self.dataSource.connector;
const args = ctx.args;
if (args && args.to) {
const dateTo = args.to;
dateTo.setHours(23, 59, 0, 0);
}
let where = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
return /^\d+$/.test(value)
? {'ii.id': value}
: {'s.name': {like: `%${value}%`}};
case 'from':
return {'ii.created': {gte: value}};
case 'to':
return {'ii.created': {lte: value}};
case 'account':
case 'fi':
return {[`s.${param}`]: value};
case 'supplierRef':
case 'serialNumber':
case 'serial':
case 'issued':
case 'isBooked':
return {[`ii.${param}`]: value};
case 'awbCode':
return {'awb.code': value};
}
});
filter = mergeFilters(filter, {where});
let stmts = [];
let stmt;
stmt = new ParameterizedSQL(
`SELECT
ii.id,
ii.serialNumber,
ii.serial,
ii.issued,
ii.isBooked,
ii.supplierRef,
ii.docFk AS dmsFk,
s.id AS supplierFk,
s.name AS supplierName,
s.account,
SUM(iid.amount) AS amount,
awb.code AS awbCode
FROM invoiceIn ii
JOIN supplier s ON s.id = ii.supplierFk
LEFT JOIN invoiceInDueDay iid ON iid.invoiceInFk = ii.id
LEFT JOIN duaInvoiceIn dii ON dii.invoiceInFk = ii.id
LEFT JOIN dua d ON d.id = dii.duaFk
LEFT JOIN awb ON awb.id = d.awbFk
LEFT JOIN company co ON co.id = ii.companyFk`
);
const sqlWhere = conn.makeWhere(filter.where);
stmt.merge(sqlWhere);
stmt.merge(`GROUP BY ii.id`);
const amount = ctx.args.amount;
if (amount) {
stmt.merge({
sql: `HAVING SUM(iid.amount) = ?`,
params: [amount],
});
}
stmt.merge(conn.makePagination(filter));
let itemsIndex = stmts.push(stmt) - 1;
let sql = ParameterizedSQL.join(stmts, ';');
let result = await conn.executeStmt(sql);
return itemsIndex === 0 ? result : result[itemsIndex];
};
};

View File

@ -0,0 +1,111 @@
const app = require('vn-loopback/server/server');
describe('InvoiceIn filter()', () => {
it('should return the invoice in matching supplier name', async() => {
let ctx = {
args: {
search: 'Plants SL',
}
};
let result = await app.models.InvoiceIn.filter(ctx);
expect(result.length).toEqual(5);
expect(result[0].supplierName).toEqual('Plants SL');
});
it('should return the invoice in matching supplier reference', async() => {
let ctx = {
args: {
supplierRef: '1241',
}
};
let result = await app.models.InvoiceIn.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].supplierRef).toEqual('1241');
});
it('should return the invoice in matching the serial number', async() => {
let ctx = {
args: {
serialNumber: '1002',
}
};
let result = await app.models.InvoiceIn.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].serialNumber).toEqual(1002);
});
it('should return the invoice in matching the account', async() => {
let ctx = {
args: {
account: '4000020002',
}
};
let result = await app.models.InvoiceIn.filter(ctx);
expect(result.length).toEqual(5);
expect(result[0].account).toEqual('4000020002');
});
it('should return the invoice in matching the awb code', async() => {
let ctx = {
args: {
awbCode: '07546491432',
}
};
let result = await app.models.InvoiceIn.filter(ctx);
const firstRow = result[0];
expect(result.length).toEqual(1);
expect(firstRow.id).toEqual(7);
expect(firstRow.awbCode).toEqual('07546491432');
});
it('should return the invoice in matching the amount', async() => {
let ctx = {
args: {
amount: '64.23',
}
};
let result = await app.models.InvoiceIn.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].amount).toEqual(64.23);
});
it('should return the invoice in matching "from" and "to"', async() => {
const from = new Date();
const to = new Date();
from.setHours(0, 0, 0, 0);
to.setHours(23, 59, 59, 999);
to.setDate(to.getDate() + 1);
const ctx = {
args: {from, to}
};
const result = await app.models.InvoiceIn.filter(ctx);
expect(result.length).toEqual(6);
});
it('should return the booked invoice in', async() => {
let ctx = {
args: {
isBooked: true,
}
};
let result = await app.models.InvoiceIn.filter(ctx);
expect(result.length).toEqual(6);
expect(result[0].isBooked).toBeTruthy();
});
});

View File

@ -0,0 +1,5 @@
{
"InvoiceIn": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/invoice-in/filter')(Self);
};

View File

@ -0,0 +1,67 @@
{
"name": "InvoiceIn",
"base": "VnModel",
"options": {
"mysql": {
"table": "invoiceIn"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"serialNumber": {
"type": "number"
},
"serial": {
"type": "string"
},
"issued": {
"type": "date"
},
"created": {
"type": "date"
},
"isBooked": {
"type": "boolean"
},
"booked": {
"type": "date"
},
"operated": {
"type": "date"
},
"dmsFk": {
"type": "number",
"mysql": {
"columnName": "docFk"
}
}
},
"relations": {
"company": {
"type": "belongsTo",
"model": "Company",
"foreignKey": "companyFk"
},
"supplier": {
"type": "belongsTo",
"model": "Supplier",
"foreignKey": "supplierFk"
},
"currency": {
"type": "belongsTo",
"model": "Currency",
"foreignKey": "currencyFk"
},
"dms": {
"type": "belongsTo",
"model": "Dms",
"foreignKey": "dmsFk"
}
}
}

View File

@ -0,0 +1,5 @@
<vn-portal slot="menu">
<vn-invoice-in-descriptor invoice-in="$ctrl.invoiceIn"></vn-invoice-in-descriptor>
<vn-left-menu source="card"></vn-left-menu>
</vn-portal>
<ui-view></ui-view>

View File

@ -0,0 +1,17 @@
import ngModule from '../module';
import ModuleCard from 'salix/components/module-card';
class Controller extends ModuleCard {
reload() {
const filter = {};
this.$http.get(`InvoiceIns/${this.$params.id}`, {filter})
.then(res => this.invoiceIn = res.data);
}
}
ngModule.vnComponent('vnInvoiceInCard', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,27 @@
import './index.js';
describe('vnInvoiceIn', () => {
let controller;
let $httpBackend;
let data = {id: 1, name: 'fooName'};
beforeEach(ngModule('invoiceIn'));
beforeEach(inject(($componentController, _$httpBackend_, $stateParams) => {
$httpBackend = _$httpBackend_;
let $element = angular.element('<div></div>');
controller = $componentController('vnInvoiceInCard', {$element});
$stateParams.id = data.id;
$httpBackend.whenRoute('GET', 'InvoiceIns/:id').respond(data);
}));
it('should request data and set it on the controller', () => {
controller.reload();
$httpBackend.flush();
expect(controller.invoiceIn).toEqual(data);
});
});

View File

@ -0,0 +1,4 @@
<slot-descriptor>
<vn-invoice-in-descriptor>
</vn-invoice-in-descriptor>
</slot-descriptor>

View File

@ -0,0 +1,9 @@
import ngModule from '../module';
import DescriptorPopover from 'salix/components/descriptor-popover';
class Controller extends DescriptorPopover {}
ngModule.vnComponent('vnInvoiceInDescriptorPopover', {
slotTemplate: require('./index.html'),
controller: Controller
});

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