Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4024-client_defaulter

This commit is contained in:
Alex Moreno 2022-05-16 14:15:37 +02:00
commit 8bcdf96aad
220 changed files with 1884 additions and 1103 deletions

14
Jenkinsfile vendored
View File

@ -62,13 +62,13 @@ pipeline {
}
}
}
// stage('Backend') {
// steps {
// nodejs('node-v14') {
// sh 'gulp launchBackTest --ci'
// }
// }
// }
stage('Backend') {
steps {
nodejs('node-v14') {
sh 'npm run test:back:ci'
}
}
}
}
}
stage('Build') {

View File

@ -54,17 +54,17 @@ $ gulp docker
For client-side unit tests run from project's root.
```
$ jest
$ npm run test:front
```
For server-side unit tests run from project's root.
```
$ gulp backTest
$ npm run test:back
```
For end-to-end tests run from project's root.
```
$ gulp e2e
$ npm run test:e2e
```
## Visual Studio Code extensions

View File

@ -1,9 +1,12 @@
const app = require('vn-loopback/server/server');
const {models} = require('vn-loopback/server/server');
describe('account changePassword()', () => {
it('should throw an error when old password is wrong', async() => {
let req = app.models.Account.changePassword(null, 1, 'wrongOldPass', 'newPass');
let err;
await models.Account.changePassword(1, 'wrongPassword', 'nightmare.9999')
.catch(error => err = error.sqlMessage);
await expectAsync(req).toBeRejected();
expect(err).toBeDefined();
expect(err).toEqual('Invalid password');
});
});

View File

@ -1,8 +1,8 @@
const app = require('vn-loopback/server/server');
// #3400 analizar que hacer con rutas de back colletion
xdescribe('newCollection()', () => {
it('return a new collection', async() => {
describe('newCollection()', () => {
it('should return a new collection', async() => {
pending('#3400 analizar que hacer con rutas de back collection');
let ctx = {req: {accessToken: {userId: 1106}}};
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1);

View File

@ -0,0 +1,57 @@
const fs = require('fs-extra');
const path = require('path');
module.exports = Self => {
Self.remoteMethod('deleteTrashFiles', {
description: 'Deletes files that have trash type',
accessType: 'WRITE',
returns: {
type: 'object',
root: true
},
http: {
path: `/deleteTrashFiles`,
verb: 'POST'
}
});
Self.deleteTrashFiles = async(options) => {
const tx = await Self.beginTransaction({});
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction)
myOptions.transaction = tx;
try {
const models = Self.app.models;
const DmsContainer = models.DmsContainer;
const trashDmsType = await models.DmsType.findOne({
where: {code: 'trash'}
}, myOptions);
const dmsToDelete = await models.Dms.find({
where: {
dmsTypeFk: trashDmsType.id
}
}, myOptions);
for (let dms of dmsToDelete) {
const pathHash = DmsContainer.getHash(dms.id);
const dmsContainer = await DmsContainer.container(pathHash);
const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file);
await fs.unlink(dstFile);
await dms.destroy(myOptions);
}
if (tx) await tx.commit();
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -47,7 +47,7 @@
"type": "date"
},
"image": {
"type": "String"
"type": "string"
}
},
"relations": {

View File

@ -9,7 +9,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},

View File

@ -8,15 +8,15 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"bic": {
"type": "String"
"type": "string"
},
"name": {
"type": "String"
"type": "string"
}
},
"relations": {

View File

@ -8,35 +8,35 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"bank": {
"type": "String",
"type": "string",
"required": true
},
"account": {
"type": "String",
"type": "string",
"required": true
},
"accountingTypeFk": {
"type": "Number",
"type": "number",
"required": true,
"mysql": {
"columnName": "cash"
}
},
"entityFk": {
"type": "Number",
"type": "number",
"required": true
},
"isActive": {
"type": "Boolean",
"type": "boolean",
"required": true
},
"currencyFk": {
"type": "Number",
"type": "number",
"required": true
}
},

View File

@ -10,20 +10,20 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"host": {
"type": "String"
"type": "string"
},
"api": {
"type": "String"
"type": "string"
},
"user": {
"type": "String"
"type": "string"
},
"password": {
"type": "String"
"type": "string"
}
},
"acls": [{

View File

@ -10,11 +10,11 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"code": {
"type": "String"
"type": "string"
},
"expired": {
"type": "date"

View File

@ -9,7 +9,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
@ -21,7 +21,7 @@
"type": "string"
},
"isUeeMember": {
"type": "Boolean"
"type": "boolean"
}
},
"relations": {

View File

@ -9,17 +9,17 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"forceId": false
},
"date": {
"type": "Date"
"type": "date"
},
"m3":{
"type": "Number"
"type": "number"
},
"warehouseFk":{
"type": "Number"
"type": "number"
}
}
}

View File

@ -9,7 +9,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},

View File

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

View File

@ -13,7 +13,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
@ -36,7 +36,7 @@
"type": "boolean"
},
"created": {
"type": "Date"
"type": "date"
}
},
"relations": {

View File

@ -9,7 +9,7 @@
"properties": {
"userFk": {
"id": true,
"type": "Number",
"type": "number",
"required": true
},
"email": {

View File

@ -8,20 +8,20 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"width": {
"type": "Number",
"type": "number",
"required": true
},
"height": {
"type": "Number",
"type": "number",
"required": true
},
"crop": {
"type": "Boolean",
"type": "boolean",
"required": true
}
},

View File

@ -8,32 +8,32 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "String",
"type": "string",
"required": true
},
"desc": {
"type": "String",
"type": "string",
"required": true
},
"maxWidth": {
"type": "Number",
"type": "number",
"required": true
},
"maxHeight": {
"type": "Number",
"type": "number",
"required": true
},
"model": {
"type": "String",
"type": "string",
"required": true
},
"property": {
"type": "String",
"type": "string",
"required": true
}
},

View File

@ -9,7 +9,7 @@
"properties": {
"code": {
"id": true,
"type": "String"
"type": "string"
}
},
"relations": {

View File

@ -11,7 +11,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier",
"mysql": {

View File

@ -9,10 +9,10 @@
"properties": {
"id": {
"id": true,
"type": "Number"
"type": "number"
},
"name": {
"type": "String"
"type": "string"
}
},
"relations": {

View File

@ -9,18 +9,18 @@
"properties": {
"id": {
"id": true,
"type": "Number"
"type": "number"
},
"userFk": {
"type": "String",
"type": "string",
"required": true
},
"tableCode": {
"type": "String",
"type": "string",
"required": true
},
"configuration": {
"type": "Object"
"type": "object"
}
},
"relations": {

View File

@ -9,40 +9,40 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"forceId": false
},
"originFk": {
"type": "Number",
"type": "number",
"required": true
},
"userFk": {
"type": "Number"
"type": "number"
},
"action": {
"type": "String",
"type": "string",
"required": true
},
"changedModel": {
"type": "String"
"type": "string"
},
"oldInstance": {
"type": "Object"
"type": "object"
},
"newInstance": {
"type": "Object"
"type": "object"
},
"creationDate": {
"type": "Date"
"type": "date"
},
"changedModelId": {
"type": "Number"
"type": "number"
},
"changedModelValue": {
"type": "String"
"type": "string"
},
"description": {
"type": "String"
"type": "string"
}
},
"relations": {

View File

@ -9,7 +9,7 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"forceId": false
},
"username":{

View File

@ -10,17 +10,17 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"forceId": false
},
"name": {
"type": "String"
"type": "string"
},
"code": {
"type": "String"
"type": "string"
},
"isInventory": {
"type": "Number"
"type": "number"
},
"isManaged":{
"type": "boolean"

24
back/nodemonConfig.json Normal file
View File

@ -0,0 +1,24 @@
{
"verbose": true,
"watch": [
"back/**/*.js",
"modules/**/*.js"
],
"ignore": [
"modules/account/front/**/*",
"modules/claim/front/**/*",
"modules/client/front/**/*",
"modules/entry/front/**/*",
"modules/invoiceIn/front/**/*",
"modules/invoiceOut/front/**/*",
"modules/item/front/**/*",
"modules/monitor/front/**/*",
"modules/order/front/**/*",
"modules/route/front/**/*",
"modules/supplier/front/**/*",
"modules/ticket/front/**/*",
"modules/travel/front/**/*",
"modules/worker/front/**/*",
"modules/zone/front/**/*"
]
}

View File

@ -1,4 +1,5 @@
require('require-yaml');
const Docker = require('../db/docker.js');
let dataSources = require('../loopback/server/datasources.json');
process.on('warning', warning => {
console.log(warning.name);
@ -6,34 +7,64 @@ process.on('warning', warning => {
console.log(warning.stack);
});
let verbose = false;
async function test() {
let isCI = false;
if (process.argv[2] === '--v')
verbose = true;
if (process.argv[2] === 'ci')
isCI = true;
let Jasmine = require('jasmine');
let jasmine = new Jasmine();
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;
const container = new Docker();
let serviceSpecs = [
`${__dirname}/**/*[sS]pec.js`,
`${__dirname}/../loopback/**/*[sS]pec.js`,
`${__dirname}/../modules/*/back/**/*.[sS]pec.js`
];
await container.run(isCI);
dataSources = JSON.parse(JSON.stringify(dataSources));
jasmine.loadConfig({
spec_dir: '.',
spec_files: serviceSpecs,
helpers: []
});
Object.assign(dataSources.vn, {
host: container.dbConf.host,
port: container.dbConf.port
});
jasmine.addReporter(new SpecReporter({
spec: {
// displayStacktrace: 'summary',
displaySuccessful: verbose,
displayFailedSpec: true,
displaySpecDuration: true
const bootOptions = {dataSources};
const app = require('vn-loopback/server/server');
app.boot(bootOptions);
const Jasmine = require('jasmine');
const jasmine = new Jasmine();
const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
jasmine.addReporter(new SpecReporter({
spec: {
displaySuccessful: isCI,
displayPending: isCI
},
summary: {
displayPending: false,
}
}));
if (isCI) {
const JunitReporter = require('jasmine-reporters');
jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
}
}));
jasmine.execute();
const backSpecs = [
'./back/**/*[sS]pec.js',
'./loopback/**/*[sS]pec.js',
'./modules/*/back/**/*.[sS]pec.js'
];
jasmine.loadConfig({
spec_dir: '.',
spec_files: backSpecs,
helpers: [],
});
jasmine.exitOnCompletion = false;
await jasmine.execute();
if (app) await app.disconnect();
if (container) await container.rm();
console.log('app disconnected & container removed');
}
test();

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
ALTER TABLE `vn`.`clientConfig` ADD `maxCreditRows` int(11) NULL COMMENT 'Máximo número de registros a mantener en la tabla clientCredit';
UPDATE `vn`.`clientConfig`
SET `maxCreditRows` = 10
WHERE `id` = 1;

View File

@ -0,0 +1,8 @@
ALTER TABLE `vn`.`propertyDms` DROP FOREIGN KEY propertyDms_FK;
ALTER TABLE `vn`.`propertyDms` ADD CONSTRAINT propertyDms_FK FOREIGN KEY (dmsFk) REFERENCES `vn`.`dms`(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `vn`.`clientDms` DROP FOREIGN KEY clientDms_ibfk_2;
ALTER TABLE `vn`.`clientDms` ADD CONSTRAINT clientDms_ibfk_2 FOREIGN KEY (dmsFk) REFERENCES `vn`.`dms`(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `vn`.`workerDocument` DROP FOREIGN KEY workerDocument_ibfk_2;
ALTER TABLE `vn`.`workerDocument` ADD CONSTRAINT workerDocument_ibfk_2 FOREIGN KEY (document) REFERENCES `vn`.`dms`(id) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,5 @@
ALTER TABLE `vn`.`dmsType` ADD monthToDelete INT UNSIGNED DEFAULT NULL NULL;
ALTER TABLE `vn`.`dmsType` MODIFY COLUMN monthToDelete int(10) unsigned DEFAULT NULL NULL COMMENT 'Meses en el pasado para ir borrando registros, dejar a null para no borrarlos nunca';
UPDATE `vn`.`dmsType`
SET monthToDelete=6
WHERE id=20;

View File

@ -0,0 +1,18 @@
DELIMITER $$
$$
CREATE TRIGGER `vn`.`dms_beforeDelete`
BEFORE DELETE
ON dms FOR EACH ROW
BEGIN
DECLARE vCanNotBeDeleted INT;
SELECT COUNT(*) INTO vCanNotBeDeleted
FROM dmsType dt
WHERE NOT (code <=> 'trash')
AND dt.id = OLD.dmsTypeFk;
IF vCanNotBeDeleted THEN
CALL util.throw('A dms can not be deleted');
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,175 @@
DROP PROCEDURE IF EXISTS vn.clean;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`clean`()
BEGIN
DECLARE vDateShort DATETIME;
DECLARE vOneYearAgo DATE;
DECLARE vFourYearsAgo DATE;
DECLARE v18Month DATE;
DECLARE v26Month DATE;
DECLARE v3Month DATE;
DECLARE vTrashId varchar(15);
SET vDateShort = TIMESTAMPADD(MONTH, -2, CURDATE());
SET vOneYearAgo = TIMESTAMPADD(YEAR,-1,CURDATE());
SET vFourYearsAgo = TIMESTAMPADD(YEAR,-4,CURDATE());
SET v18Month = TIMESTAMPADD(MONTH, -18,CURDATE());
SET v26Month = TIMESTAMPADD(MONTH, -26,CURDATE());
SET v3Month = TIMESTAMPADD(MONTH, -3, CURDATE());
DELETE FROM ticketParking WHERE created < vDateShort;
DELETE FROM routesMonitor WHERE dated < vDateShort;
DELETE FROM workerTimeControlLog WHERE created < vDateShort;
DELETE FROM `message` WHERE sendDate < vDateShort;
DELETE FROM messageInbox WHERE sendDate < vDateShort;
DELETE FROM messageInbox WHERE sendDate < vDateShort;
DELETE FROM workerTimeControl WHERE timed < vFourYearsAgo;
DELETE FROM itemShelving WHERE created < CURDATE() AND visible = 0;
DELETE FROM ticketDown WHERE created < TIMESTAMPADD(DAY,-1,CURDATE());
DELETE FROM entryLog WHERE creationDate < vDateShort;
DELETE IGNORE FROM expedition WHERE created < v26Month;
DELETE FROM sms WHERE created < v18Month;
DELETE FROM saleTracking WHERE created < vOneYearAgo;
DELETE tobs FROM ticketObservation tobs
JOIN ticket t ON tobs.ticketFk = t.id WHERE t.shipped < TIMESTAMPADD(YEAR,-2,CURDATE());
DELETE sc.* FROM saleCloned sc JOIN sale s ON s.id = sc.saleClonedFk JOIN ticket t ON t.id = s.ticketFk WHERE t.shipped < vOneYearAgo;
DELETE FROM sharingCart where ended < vDateShort;
DELETE FROM sharingClient where ended < vDateShort;
DELETE tw.* FROM ticketWeekly tw
LEFT JOIN sale s ON s.ticketFk = tw.ticketFk WHERE s.itemFk IS NULL;
DELETE FROM claim WHERE ticketCreated < vFourYearsAgo;
DELETE FROM message WHERE sendDate < vDateShort;
-- Robert ubicacion anterior de trevelLog comentario para debug
DELETE sc FROM saleChecked sc
JOIN sale s ON sc.saleFk = s.id WHERE s.created < vDateShort;
DELETE FROM zoneEvent WHERE `type` = 'day' AND dated < v3Month;
DELETE bm
FROM buyMark bm
JOIN buy b ON b.id = bm.id
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed <= vDateShort;
DELETE FROM stowaway WHERE created < v3Month;
DELETE FROM vn.buy WHERE created < vDateShort AND entryFk = 9200;
DELETE FROM vn.itemShelvingLog WHERE created < vDateShort;
DELETE FROM vn.stockBuyed WHERE creationDate < vDateShort;
-- Equipos duplicados
DELETE w.*
FROM workerTeam w
JOIN (SELECT id, team, workerFk, COUNT(*) - 1 as duplicated
FROM workerTeam
GROUP BY team,workerFk
HAVING duplicated
) d ON d.team = w.team AND d.workerFk = w.workerFk AND d.id != w.id;
DELETE sc
FROM saleComponent sc
JOIN sale s ON s.id= sc.saleFk
JOIN ticket t ON t.id= s.ticketFk
WHERE t.shipped < v18Month;
DELETE c
FROM vn.claim c
JOIN vn.claimState cs ON cs.id = c.claimStateFk
WHERE cs.description = "Anulado" AND
c.created < vDateShort;
DELETE
FROM vn.expeditionTruck
WHERE ETD < v3Month;
-- borrar travels sin entradas
DROP TEMPORARY TABLE IF EXISTS tmp.thermographToDelete;
CREATE TEMPORARY TABLE tmp.thermographToDelete
SELECT th.id,th.dmsFk
FROM vn.travel t
LEFT JOIN vn.entry e ON e.travelFk = t.id
JOIN vn.travelThermograph th ON th.travelFk = t.id
WHERE t.shipped < TIMESTAMPADD(MONTH, -3, CURDATE()) AND e.travelFk IS NULL;
SELECT dt.id into vTrashId
FROM vn.dmsType dt
WHERE dt.code = 'trash';
UPDATE tmp.thermographToDelete th
JOIN vn.dms d ON d.id = th.dmsFk
SET d.dmsTypeFk = vTrashId;
DELETE th
FROM tmp.thermographToDelete tmp
JOIN vn.travelThermograph th ON th.id = tmp.id;
DELETE t
FROM vn.travel t
LEFT JOIN vn.entry e ON e.travelFk = t.id
WHERE t.shipped < TIMESTAMPADD(MONTH, -3, CURDATE()) AND e.travelFk IS NULL;
UPDATE dms d
JOIN dmsType dt ON dt.id = d.dmsTypeFk
SET d.dmsTypeFk = vTrashId
WHERE created < TIMESTAMPADD(MONTH, -dt.monthToDelete, CURDATE());
-- borrar entradas sin compras
DROP TEMPORARY TABLE IF EXISTS tmp.entryToDelete;
CREATE TEMPORARY TABLE tmp.entryToDelete
SELECT e.*
FROM vn.entry e
LEFT JOIN vn.buy b ON b.entryFk = e.id
JOIN vn.entryConfig ec ON e.id != ec.defaultEntry
WHERE e.dated < TIMESTAMPADD(MONTH, -3, CURDATE()) AND b.entryFK IS NULL;
DELETE e
FROM vn.entry e
JOIN tmp.entryToDelete tmp ON tmp.id = e.id;
-- borrar de route registros menores a 4 años
DROP TEMPORARY TABLE IF EXISTS tmp.routeToDelete;
CREATE TEMPORARY TABLE tmp.routeToDelete
SELECT *
FROM vn.route r
WHERE created < TIMESTAMPADD(YEAR,-4,CURDATE());
UPDATE tmp.routeToDelete tmp
JOIN vn.dms d ON d.id = tmp.gestdocFk
SET d.dmsTypeFk = vTrashId;
DELETE r
FROM tmp.routeToDelete tmp
JOIN vn.route r ON r.id = tmp.id;
-- borrar registros de dua y awb menores a 2 años
DROP TEMPORARY TABLE IF EXISTS tmp.duaToDelete;
CREATE TEMPORARY TABLE tmp.duaToDelete
SELECT *
FROM vn.dua
WHERE operated < TIMESTAMPADD(YEAR,-2,CURDATE());
UPDATE tmp.duaToDelete tm
JOIN vn.dms d ON d.id = tm.gestdocFk
SET d.dmsTypeFk = vTrashId;
DELETE d
FROM tmp.duaToDelete tmp
JOIN vn.dua d ON d.id = tmp.id;
DELETE FROM vn.awb WHERE created < TIMESTAMPADD(YEAR,-2,CURDATE());
-- Borra los ficheros gestDoc
INSERT INTO vn.printServerQueue(priorityFk, labelReportFk)VALUES(1,11);
-- Borra los registros de collection y ticketcollection
DELETE FROM vn.collection WHERE created < vDateShort;
DROP TEMPORARY TABLE IF EXISTS tmp.thermographToDelete;
DROP TEMPORARY TABLE IF EXISTS tmp.entryToDelete;
DROP TEMPORARY TABLE IF EXISTS tmp.duaToDelete;
DELETE FROM travelLog WHERE creationDate < v3Month;
CALL shelving_clean;
END$$
DELIMITER ;

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId)
VALUES ('Dms','deleteTrashFiles','WRITE','ALLOW','ROLE','employee')

View File

@ -1 +0,0 @@
Delete file

View File

View File

@ -24,7 +24,10 @@ module.exports = class Docker {
let d = new Date();
let pad = v => v < 10 ? '0' + v : v;
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
log('Building container image...');
await this.execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./db`);
log('Image built.');
let dockerArgs;
@ -39,6 +42,7 @@ module.exports = class Docker {
let runChown = process.platform != 'linux';
log('Starting container...');
const container = await this.execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`);
this.id = container.stdout.trim();
@ -158,6 +162,7 @@ module.exports = class Docker {
return reject(new Error('Docker exited, please see the docker logs for more info'));
let conn = mysql.createConnection(myConf);
conn.on('error', () => {});
conn.connect(err => {
conn.destroy();

View File

@ -313,9 +313,9 @@ INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`)
(1103, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(1104, -30, DATE_ADD(CURDATE(), INTERVAL -1 MONTH));
INSERT INTO `vn`.`clientConfig`(`riskTolerance`)
INSERT INTO `vn`.`clientConfig`(`riskTolerance`, `maxCreditRows`)
VALUES
(200);
(200, 10);
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`)
VALUES
@ -393,17 +393,17 @@ DROP TEMPORARY TABLE tmp.address;
INSERT INTO `vn`.`clientCredit`(`id`, `clientFk`, `workerFk`, `amount`, `created`)
VALUES
(1 , 1101, 5, 300, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(2 , 1101, 5, 900, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(3 , 1101, 5, 800, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
(4 , 1101, 5, 700, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
(5 , 1101, 5, 600, DATE_ADD(CURDATE(), INTERVAL -5 MONTH)),
(1 , 1101, 5, 300, DATE_ADD(CURDATE(), INTERVAL -11 MONTH)),
(2 , 1101, 5, 900, DATE_ADD(CURDATE(), INTERVAL -10 MONTH)),
(3 , 1101, 5, 800, DATE_ADD(CURDATE(), INTERVAL -9 MONTH)),
(4 , 1101, 5, 700, DATE_ADD(CURDATE(), INTERVAL -8 MONTH)),
(5 , 1101, 5, 600, DATE_ADD(CURDATE(), INTERVAL -7 MONTH)),
(6 , 1101, 5, 500, DATE_ADD(CURDATE(), INTERVAL -6 MONTH)),
(7 , 1101, 5, 400, DATE_ADD(CURDATE(), INTERVAL -7 MONTH)),
(8 , 1101, 9, 300, DATE_ADD(CURDATE(), INTERVAL -8 MONTH)),
(9 , 1101, 9, 200, DATE_ADD(CURDATE(), INTERVAL -9 MONTH)),
(10, 1101, 9, 100, DATE_ADD(CURDATE(), INTERVAL -10 MONTH)),
(11, 1101, 9, 50 , DATE_ADD(CURDATE(), INTERVAL -11 MONTH)),
(7 , 1101, 5, 400, DATE_ADD(CURDATE(), INTERVAL -5 MONTH)),
(8 , 1101, 9, 300, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
(9 , 1101, 9, 200, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
(10, 1101, 9, 100, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(11, 1101, 9, 50 , DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(12, 1102, 9, 800, CURDATE()),
(14, 1104, 9, 90 , CURDATE()),
(15, 1105, 9, 90 , CURDATE());
@ -854,18 +854,35 @@ INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPack
('cc', 1640038.00, 56.00, 220.00, 128.00, 1, CURDATE(), 15, 90.00),
('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, CURDATE(), 16, 0.00);
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`, `externalId`, `packagingFk`)
INSERT INTO `vn`.`expeditionStateType`(`id`, `description`, `code`)
VALUES
(1, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 15, 1, 1, 18, 'UR9000006041', 94),
(2, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 16, 2, 1, 18, 'UR9000006041', 94),
(3, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 3, 1, 18, 'UR9000006041', 94),
(4, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 4, 1, 18, 'UR9000006041', 94),
(5, 1, 2, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94),
(6, 7, 3, 71, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), NULL, 1, 1, 18, NULL, 94),
(7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL, 1, 1, 18, NULL, 94),
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), NULL, 1, 1, 18, NULL, 94),
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94),
(10, 7, 7, 71, NOW(), NULL, 1, 1, 18, NULL, 94);
(1, 'En reparto', 'ON DELIVERY'),
(2, 'Entregada', 'DELIVERED'),
(3, 'Perdida', 'LOST');
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`, `externalId`, `packagingFk`, `stateTypeFk`)
VALUES
(1, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 15, 1, 1, 18, 'UR9000006041', 94, 1),
(2, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 16, 2, 1, 18, 'UR9000006041', 94, 1),
(3, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 3, 1, 18, 'UR9000006041', 94, 2),
(4, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 4, 1, 18, 'UR9000006041', 94, 2),
(5, 1, 2, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94, 3),
(6, 7, 3, 71, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), NULL, 1, 1, 18, NULL, 94, 3),
(7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL, 1, 1, 18, NULL, 94, NULL),
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), NULL, 1, 1, 18, NULL, 94, 1),
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94, 2),
(10, 7, 7, 71, NOW(), NULL, 1, 1, 18, NULL, 94, 3);
INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`)
VALUES
(1, CURDATE(), 1, 1, 1),
(2, CURDATE(), 2, 1, 1),
(3, CURDATE(), 3, 1, 1),
(4, CURDATE(), 3, 2, 1106),
(5, CURDATE(), 5, 1, 1106),
(6, CURDATE(), 5, 3, 1106);
INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`)
VALUES
@ -1296,11 +1313,11 @@ INSERT INTO `vn`.`supplierAddress`(`id`, `supplierFk`, `nickname`, `street`, `pr
(5, 442, 'GCR building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222'),
(6, 442, 'The Gotham Tonight building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222');
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`, `commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`)
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`, `commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`, `healthRegister`)
VALUES
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'flowerPlants', 1);
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1, '400664487V'),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V');
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
VALUES

View File

@ -982,8 +982,8 @@ export default {
save: 'vn-invoice-in-basic-data button[type=submit]'
},
invoiceInTax: {
addTaxButton: 'vn-invoice-in-tax vn-icon-button[icon="add_circle"]',
thirdExpence: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.expenseFk"]',
addTaxButton: 'vn-invoice-in-tax vn-icon-button[vn-tooltip="Add tax"]',
thirdExpense: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.expenseFk"]',
thirdTaxableBase: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-input-number[ng-model="invoiceInTax.taxableBase"]',
thirdTaxType: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.taxTypeSageFk"]',
thirdTransactionType: 'vn-invoice-in-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="invoiceInTax.transactionTypeSageFk"]',

87
e2e/helpers/tests.js Normal file
View File

@ -0,0 +1,87 @@
require('@babel/register')({presets: ['@babel/env']});
require('core-js/stable');
require('regenerator-runtime/runtime');
const axios = require('axios');
const Docker = require('../../db/docker.js');
const e2eConfig = require('./config.js');
const log = require('fancy-log');
process.on('warning', warning => {
console.log(warning.name);
console.log(warning.message);
console.log(warning.stack);
});
async function test() {
if (process.argv[2] === 'show')
process.env.E2E_SHOW = true;
const container = new Docker('salix-db');
await container.run();
const Jasmine = require('jasmine');
const jasmine = new Jasmine();
const specFiles = [
`./e2e/paths/01*/*[sS]pec.js`,
`./e2e/paths/02*/*[sS]pec.js`,
`./e2e/paths/03*/*[sS]pec.js`,
`./e2e/paths/04*/*[sS]pec.js`,
`./e2e/paths/05*/*[sS]pec.js`,
`./e2e/paths/06*/*[sS]pec.js`,
`./e2e/paths/07*/*[sS]pec.js`,
`./e2e/paths/08*/*[sS]pec.js`,
`./e2e/paths/09*/*[sS]pec.js`,
`./e2e/paths/10*/*[sS]pec.js`,
`./e2e/paths/11*/*[sS]pec.js`,
`./e2e/paths/12*/*[sS]pec.js`,
`./e2e/paths/13*/*[sS]pec.js`,
`./e2e/paths/**/*[sS]pec.js`
];
jasmine.loadConfig({
spec_dir: '.',
spec_files: specFiles,
helpers: [],
random: false,
});
await backendStatus();
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
await jasmine.execute();
}
async function backendStatus() {
log('Awaiting backend connection...');
const milliseconds = 1000;
const maxAttempts = 10;
return new Promise(resolve => {
let timer;
let attempts = 1;
timer = setInterval(async() => {
try {
attempts++;
const url = `${e2eConfig.url}/api/Applications/status`;
const {data} = await axios.get(url);
if (data == true) {
clearInterval(timer);
log('Backend connection stablished!');
resolve(attempts);
}
} catch (error) {
if (error && attempts >= maxAttempts) {
log('Could not connect to backend');
process.exit();
}
}
}, milliseconds);
});
}
test();

View File

@ -19,7 +19,7 @@ describe('InvoiceIn tax path', () => {
it('should add a new tax', async() => {
await page.waitToClick(selectors.invoiceInTax.addTaxButton);
await page.autocompleteSearch(selectors.invoiceInTax.thirdExpence, '6210000567');
await page.autocompleteSearch(selectors.invoiceInTax.thirdExpense, '6210000567');
await page.write(selectors.invoiceInTax.thirdTaxableBase, '100');
await page.autocompleteSearch(selectors.invoiceInTax.thirdTaxType, '6');
await page.autocompleteSearch(selectors.invoiceInTax.thirdTransactionType, 'Operaciones exentas');
@ -37,9 +37,9 @@ describe('InvoiceIn tax path', () => {
expect(result).toEqual('Taxable base €1,323.16');
});
it('should navigate back to the tax section and check the reciently added line contains the expected expense', async() => {
it('should navigate back to tax section, check the reciently added line contains the expected expense', async() => {
await page.accessToSection('invoiceIn.card.tax');
const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpence, 'value');
const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpense, 'value');
expect(result).toEqual('6210000567: Alquiler VNH');
});

View File

@ -5,12 +5,14 @@
</vn-check>
<vn-icon-button
class="vn-pl-none"
ng-if="$ctrl.checked && $ctrl.checkDummyEnabled"
ng-if="$ctrl.isCheckedDummy()"
icon="expand_more"
vn-popover="menu"
ng-click="$ctrl.countRows()">
</vn-icon-button>
<vn-menu vn-id="menu">
<vn-menu
vn-id="menu"
ng-if="$ctrl.isCheckedDummy()">
<vn-list>
<span translate>All</span>
<span class="bold">

View File

@ -172,6 +172,10 @@ export default class MultiCheck extends FormInput {
this.checkedDummyCount = this.allRowsCount;
}
isCheckedDummy() {
return this.checked && this.checkDummyEnabled;
}
/**
* Toggles checked property on
* all instances

View File

@ -190,4 +190,30 @@ describe('Component vnMultiCheck', () => {
expect(controller.checkedDummyCount).toBeNull();
});
});
describe('isCheckedDummy()', () => {
it(`should return true only if is checked and checked dummy is enabled`, () => {
controller.checked = true;
controller.checkDummyEnabled = true;
const isCheckedDummy = controller.isCheckedDummy();
expect(isCheckedDummy).toEqual(true);
});
it(`should return false if not checked`, () => {
controller.checked = false;
controller.checkDummyEnabled = true;
const isCheckedDummy = controller.isCheckedDummy();
expect(isCheckedDummy).toEqual(false);
});
it(`should return false if checked dummy is disabled`, () => {
controller.checked = true;
controller.checkDummyEnabled = false;
const isCheckedDummy = controller.isCheckedDummy();
expect(isCheckedDummy).toEqual(false);
});
});
});

View File

@ -3,15 +3,8 @@ vn-multi-check {
.vn-check {
margin-bottom: 12px
}
vn-list{
padding: 50px;
}
vn-menu{
padding: 50px;
}
}
.bold{
font-weight: bold;
}

View File

@ -3,8 +3,6 @@ const gulp = require('gulp');
const PluginError = require('plugin-error');
const argv = require('minimist')(process.argv.slice(2));
const log = require('fancy-log');
const got = require('got');
const e2eConfig = require('./e2e/helpers/config.js');
const Docker = require('./db/docker.js');
// Configuration
@ -67,187 +65,6 @@ back.description = `Starts backend and database service`;
const defaultTask = gulp.parallel(front, back);
defaultTask.description = `Starts all application services`;
// Backend tests - Private method
async function launchBackTest(done) {
let err;
let dataSources = require('./loopback/server/datasources.json');
const container = new Docker();
await container.run(argv.ci);
dataSources = JSON.parse(JSON.stringify(dataSources));
Object.assign(dataSources.vn, {
host: container.dbConf.host,
port: container.dbConf.port
});
let bootOptions = {dataSources};
let app = require(`./loopback/server/server`);
try {
app.boot(bootOptions);
await new Promise((resolve, reject) => {
const jasmine = require('gulp-jasmine');
const options = {
verbose: false,
includeStackTrace: false,
errorOnFail: false,
timeout: 5000,
config: {}
};
if (argv.ci) {
const reporters = require('jasmine-reporters');
options.reporter = new reporters.JUnitXmlReporter();
}
let backSpecFiles = [
'back/**/*.spec.js',
'loopback/**/*.spec.js',
'modules/*/back/**/*.spec.js'
];
gulp.src(backSpecFiles)
.pipe(jasmine(options))
.on('end', resolve)
.on('error', reject)
.resume();
});
} catch (e) {
err = e;
}
await app.disconnect();
await container.rm();
done();
if (err)
throw err;
}
launchBackTest.description = `
Runs the backend tests once using a random container, can receive --ci arg to save reports on a xml file`;
// Backend tests
function backTest(done) {
const nodemon = require('gulp-nodemon');
nodemon({
exec: ['node --tls-min-v1.0 ./node_modules/gulp/bin/gulp.js'],
args: ['launchBackTest'],
watch: backSources,
done: done
});
}
backTest.description = `Watches for changes in modules to execute backTest task`;
// End to end tests
function e2eSingleRun() {
require('@babel/register')({presets: ['@babel/env']});
require('core-js/stable');
require('regenerator-runtime/runtime');
const jasmine = require('gulp-jasmine');
const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
if (argv.show || argv.s)
process.env.E2E_SHOW = true;
const specFiles = [
`${__dirname}/e2e/paths/01*/*[sS]pec.js`,
`${__dirname}/e2e/paths/02*/*[sS]pec.js`,
`${__dirname}/e2e/paths/03*/*[sS]pec.js`,
`${__dirname}/e2e/paths/04*/*[sS]pec.js`,
`${__dirname}/e2e/paths/05*/*[sS]pec.js`,
`${__dirname}/e2e/paths/06*/*[sS]pec.js`,
`${__dirname}/e2e/paths/07*/*[sS]pec.js`,
`${__dirname}/e2e/paths/08*/*[sS]pec.js`,
`${__dirname}/e2e/paths/09*/*[sS]pec.js`,
`${__dirname}/e2e/paths/10*/*[sS]pec.js`,
`${__dirname}/e2e/paths/11*/*[sS]pec.js`,
`${__dirname}/e2e/paths/12*/*[sS]pec.js`,
`${__dirname}/e2e/paths/13*/*[sS]pec.js`,
`${__dirname}/e2e/paths/**/*[sS]pec.js`
];
return gulp.src(specFiles).pipe(jasmine({
errorOnFail: false,
timeout: 30000,
config: {
random: false,
// TODO: Waiting for this option to be implemented
// https://github.com/jasmine/jasmine/issues/1533
stopSpecOnExpectationFailure: false
},
reporter: [
new SpecReporter({
spec: {
displayStacktrace: 'none',
displaySuccessful: true,
displayFailedSpec: true,
displaySpecDuration: true,
},
summary: {
displayStacktrace: 'raw',
displayPending: false
},
colors: {
enabled: true,
successful: 'brightGreen',
failed: 'brightRed'
},
// stacktrace: {
// filter: stacktrace => {
// const lines = stacktrace.split('\n');
// const filtered = [];
// for (let i = 1; i < lines.length; i++) {
// if (/e2e\/paths/.test(lines[i]))
// filtered.push(lines[i]);
// }
// return filtered.join('\n');
// }
// }
})
]
}));
}
e2e = gulp.series(docker, async function isBackendReady() {
const attempts = await backendStatus();
log(`Backend ready after ${attempts} attempt(s)`);
return attempts;
}, e2eSingleRun);
e2e.description = `Restarts database and runs the e2e tests`;
async function backendStatus() {
const milliseconds = 250;
return new Promise(resolve => {
let timer;
let attempts = 1;
timer = setInterval(async() => {
try {
const url = `${e2eConfig.url}/api/Applications/status`;
const {body} = await got.get(url);
if (body == 'true') {
clearInterval(timer);
resolve(attempts);
} else
attempts++;
} catch (error) {
if (error || attempts > 100) // 250ms * 100 => 25s timeout
throw new Error('Could not connect to backend');
}
}, milliseconds);
});
}
backendStatus.description = `Performs a simple requests to check the backend status`;
function install() {
const install = require('gulp-install');
const print = require('gulp-print');
@ -431,9 +248,6 @@ module.exports = {
back,
backOnly,
backWatch,
backTest,
launchBackTest,
e2e,
i,
install,
build,
@ -444,6 +258,5 @@ module.exports = {
locales,
localesRoutes,
watch,
docker,
backendStatus,
docker
};

View File

@ -47,5 +47,6 @@ module.exports = {
'^.+\\.js?$': 'babel-jest',
'^.+\\.html$': 'html-loader-jest'
},
reporters: ['default', 'jest-junit']
};

View File

@ -9,19 +9,19 @@
"properties": {
"id": {
"id": true,
"type": "Number"
"type": "number"
},
"model": {
"type": "String"
"type": "string"
},
"property":{
"type": "String"
"type": "string"
},
"actionType":{
"type": "String"
"type": "string"
},
"role":{
"type": "String"
"type": "string"
}
}
}

View File

@ -29,7 +29,7 @@
"type": "string"
},
"verifyCert": {
"type": "Boolean"
"type": "boolean"
}
}
}

View File

@ -11,7 +11,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true
}
}

View File

@ -8,7 +8,7 @@
},
"properties": {
"userFk": {
"type": "Number",
"type": "number",
"id": true,
"description": "The user id",
"mysql": {
@ -16,7 +16,7 @@
}
},
"extension": {
"type": "String",
"type": "string",
"required": true
}
},

View File

@ -13,12 +13,12 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"quantity": {
"type": "Number",
"type": "number",
"required": true
}
},

View File

@ -8,12 +8,12 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"description": {
"type": "String",
"type": "string",
"required": true
}
},

View File

@ -12,7 +12,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},

View File

@ -17,7 +17,7 @@
],
"properties": {
"dmsFk": {
"type": "Number",
"type": "number",
"id": true,
"required": true
}

View File

@ -12,7 +12,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
}

View File

@ -9,40 +9,40 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"forceId": false
},
"originFk": {
"type": "Number",
"type": "number",
"required": true
},
"userFk": {
"type": "Number"
"type": "number"
},
"action": {
"type": "String",
"type": "string",
"required": true
},
"changedModel": {
"type": "String"
"type": "string"
},
"oldInstance": {
"type": "Object"
"type": "object"
},
"newInstance": {
"type": "Object"
"type": "object"
},
"creationDate": {
"type": "Date"
"type": "date"
},
"changedModelId": {
"type": "Number"
"type": "number"
},
"changedModelValue": {
"type": "String"
"type": "string"
},
"description": {
"type": "String"
"type": "string"
}
},
"relations": {

View File

@ -9,23 +9,23 @@
"validateUpsert": true,
"properties": {
"clientFk": {
"type": "Number",
"type": "number",
"id": true
},
"yearSale": {
"type": "Number"
"type": "number"
},
"claimAmount": {
"type": "Number"
"type": "number"
},
"claimingRate": {
"type": "Number"
"type": "number"
},
"priceIncreasing": {
"type": "Number"
"type": "number"
},
"packingRate": {
"type": "Number"
"type": "number"
}
},
"relations": {

View File

@ -8,12 +8,12 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"description": {
"type": "String"
"type": "string"
}
},
"acls": [

View File

@ -8,12 +8,12 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"description": {
"type": "String",
"type": "string",
"required": true
}
},

View File

@ -8,16 +8,16 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"description": {
"type": "String",
"type": "string",
"required": true
},
"responsability": {
"type": "Number",
"type": "number",
"required": true
}
},

View File

@ -8,12 +8,12 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"description": {
"type": "String"
"type": "string"
}
},
"acls": [

View File

@ -12,7 +12,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},

View File

@ -12,11 +12,13 @@ describe('Client updatePortfolio', () => {
const expectedResult = 841.63;
await models.Client.rawSql(`UPDATE vn.client SET salesPersonFk = ${salesPersonId} WHERE id = ${clientId}; `);
const clientQuery = `UPDATE vn.client SET salesPersonFk = ${salesPersonId} WHERE id = ${clientId}; `;
await models.Client.rawSql(clientQuery);
await models.Client.updatePortfolio();
let [salesPerson] = await models.Client.rawSql(`SELECT portfolioWeight FROM bs.salesPerson WHERE workerFk = ${salesPersonId}; `, null, options);
const portfolioQuery = `SELECT portfolioWeight FROM bs.salesPerson WHERE workerFk = ${salesPersonId}; `;
const [salesPerson] = await models.Client.rawSql(portfolioQuery, null, options);
expect(salesPerson.portfolioWeight).toEqual(expectedResult);
@ -26,8 +28,9 @@ describe('Client updatePortfolio', () => {
throw e;
}
});
// task 3817
xit('should keep the same portfolioWeight when a salesperson is unassigned of a client', async() => {
it('should keep the same portfolioWeight when a salesperson is unassigned of a client', async() => {
pending('task 3817');
const salesPersonId = 19;
const tx = await models.Client.beginTransaction({});
@ -40,7 +43,8 @@ describe('Client updatePortfolio', () => {
await models.Client.updatePortfolio();
let [salesPerson] = await models.Client.rawSql(`SELECT portfolioWeight FROM bs.salesPerson WHERE workerFk = ${salesPersonId}; `, null, options);
const portfolioQuery = `SELECT portfolioWeight FROM bs.salesPerson WHERE workerFk = ${salesPersonId}; `;
const [salesPerson] = await models.Client.rawSql(portfolioQuery, null, options);
expect(salesPerson.portfolioWeight).toEqual(expectedResult);

View File

@ -14,6 +14,9 @@
"Client": {
"dataSource": "vn"
},
"ClientConfig": {
"dataSource": "vn"
},
"ClientContact": {
"dataSource": "vn"
},

View File

@ -8,7 +8,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},

View File

@ -14,7 +14,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
@ -43,10 +43,10 @@
"type": "boolean"
},
"longitude": {
"type": "Number"
"type": "number"
},
"latitude": {
"type": "Number"
"type": "number"
},
"isEqualizated": {
"type": "boolean"

View File

@ -0,0 +1,22 @@
{
"name": "ClientConfig",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientConfig"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"riskTolerance": {
"type": "number"
},
"maxCreditRows": {
"type": "number"
}
}
}

View File

@ -3,34 +3,34 @@
"description": "Client phone contacts",
"base": "Loggable",
"log": {
"model": "ClientLog",
"relation": "client",
"showField": "name"
"model": "ClientLog",
"relation": "client",
"showField": "name"
},
"options": {
"mysql": {
"table": "clientContact"
}
"mysql": {
"table": "clientContact"
}
},
"validateUpsert": true,
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "string"
},
"phone": {
"type": "string"
}
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "string"
},
"phone": {
"type": "string"
}
},
"relations": {
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
}
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
}
}
}
}

View File

@ -1,26 +1,26 @@
{
"name": "ClientCreditLimit",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientCreditLimit"
}
},
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
"name": "ClientCreditLimit",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientCreditLimit"
}
},
"maxAmount": {
"type": "Number"
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"maxAmount": {
"type": "number"
}
},
"relations": {
"role": {
"type": "belongsTo",
"model": "Role",
"foreignKey": "roleFk"
}
}
},
"relations": {
"role": {
"type": "belongsTo",
"model": "Role",
"foreignKey": "roleFk"
}
}
}

View File

@ -0,0 +1,23 @@
module.exports = Self => {
Self.observe('after save', async ctx => {
const instance = ctx.instance;
const models = Self.app.models;
const clientConfig = await models.ClientConfig.findOne();
const maxCreditRows = clientConfig.maxCreditRows;
const clientCredit = await models.ClientCredit.find({
where: {clientFk: instance.clientFk},
order: 'created DESC',
limit: maxCreditRows
}, ctx.options);
const lastCredit = clientCredit[maxCreditRows - 1];
if (lastCredit) {
await models.ClientCredit.destroyAll({
clientFk: instance.clientFk,
created: {lt: lastCredit.created}
}, ctx.options);
}
});
};

View File

@ -1,36 +1,36 @@
{
"name": "ClientCredit",
"description": "Log of credit changes",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientCredit"
}
},
"validateUpsert": true,
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
"name": "ClientCredit",
"description": "Log of credit changes",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientCredit"
}
},
"amount": {
"type": "Number"
"validateUpsert": true,
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"amount": {
"type": "number"
},
"created": {
"type": "date"
}
},
"created": {
"type": "date"
"relations": {
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
},
"worker": {
"type": "belongsTo",
"model": "Worker",
"foreignKey": "workerFk"
}
}
},
"relations": {
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
},
"worker": {
"type": "belongsTo",
"model": "Worker",
"foreignKey": "workerFk"
}
}
}

View File

@ -13,12 +13,12 @@
},
"properties": {
"dmsFk": {
"type": "Number",
"type": "number",
"id": true,
"required": true
},
"clientFk": {
"type": "Number",
"type": "number",
"required": true
}
},

View File

@ -9,40 +9,40 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"forceId": false
},
"originFk": {
"type": "Number",
"type": "number",
"required": true
},
"userFk": {
"type": "Number"
"type": "number"
},
"action": {
"type": "String",
"type": "string",
"required": true
},
"changedModel": {
"type": "String"
"type": "string"
},
"oldInstance": {
"type": "Object"
"type": "object"
},
"newInstance": {
"type": "Object"
"type": "object"
},
"creationDate": {
"type": "Date"
"type": "date"
},
"changedModelId": {
"type": "Number"
"type": "number"
},
"changedModelValue": {
"type": "String"
"type": "string"
},
"description": {
"type": "String"
"type": "string"
}
},
"relations": {

View File

@ -13,12 +13,12 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"clientFk": {
"type": "Number"
"type": "number"
},
"text": {
"type": "string",

View File

@ -2,22 +2,22 @@
"name": "ClientRisk",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientRisk"
}
"mysql": {
"table": "clientRisk"
}
},
"properties": {
"clientFk": {
"type": "Number",
"id": true
},
"companyFk": {
"type": "Number",
"id": true
},
"amount": {
"type": "Number"
}
"clientFk": {
"type": "number",
"id": true
},
"companyFk": {
"type": "number",
"id": true
},
"amount": {
"type": "number"
}
},
"relations": {
"client": {
@ -31,4 +31,4 @@
"foreignKey": "companyFk"
}
}
}
}

View File

@ -14,7 +14,7 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"created": {

View File

@ -8,17 +8,17 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true
},
"code": {
"type": "String"
"type": "string"
},
"type": {
"type": "String"
"type": "string"
},
"isCreatedAsServed": {
"type": "Number"
"type": "number"
}
}
}

View File

@ -2,21 +2,21 @@
"name": "ClientUnpaid",
"base": "VnModel",
"options": {
"mysql": {
"table": "clientUnpaid"
}
"mysql": {
"table": "clientUnpaid"
}
},
"properties": {
"clientFk": {
"type": "number",
"id": true
},
"dated": {
"type": "date"
},
"amount": {
"type": "Number"
}
"clientFk": {
"type": "number",
"id": true
},
"dated": {
"type": "date"
},
"amount": {
"type": "number"
}
},
"relations": {
"client": {

View File

@ -12,7 +12,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
@ -55,16 +55,16 @@
"type": "boolean"
},
"credit": {
"type": "Number"
"type": "number"
},
"creditInsurance": {
"type": "Number"
"type": "number"
},
"iban": {
"type": "string"
},
"dueDay": {
"type": "Number"
"type": "number"
},
"isEqualizated": {
"type": "boolean",
@ -105,7 +105,7 @@
"type": "boolean"
},
"quality": {
"type": "Number"
"type": "number"
},
"isVies": {
"type": "boolean"
@ -117,7 +117,7 @@
"type": "string"
},
"created": {
"type": "Date"
"type": "date"
},
"sageTaxTypeFk": {
"type": "number",

View File

@ -1,20 +1,20 @@
{
"name": "ContactChannel",
"base": "VnModel",
"options": {
"mysql": {
"table": "contactChannel"
}
},
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
"name": "ContactChannel",
"base": "VnModel",
"options": {
"mysql": {
"table": "contactChannel"
}
},
"name": {
"type": "string",
"required": true
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "string",
"required": true
}
}
}
}

View File

@ -1,42 +1,42 @@
{
"name": "CreditClassification",
"description": "Clasified clients",
"base": "VnModel",
"options": {
"mysql": {
"table": "creditClassification"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
"name": "CreditClassification",
"description": "Clasified clients",
"base": "VnModel",
"options": {
"mysql": {
"table": "creditClassification"
}
},
"started": {
"type": "date",
"required": true,
"mysql": {
"columnName": "dateStart"
}
"properties": {
"id": {
"id": true,
"type": "number",
"description": "Identifier"
},
"started": {
"type": "date",
"required": true,
"mysql": {
"columnName": "dateStart"
}
},
"finished": {
"type": "date",
"mysql": {
"columnName": "dateEnd"
}
}
},
"finished": {
"type": "date",
"mysql": {
"columnName": "dateEnd"
}
"relations": {
"customer": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "client"
},
"insurances": {
"type": "hasMany",
"model": "CreditInsurance",
"foreignKey": "creditClassification"
}
}
},
"relations": {
"customer": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "client"
},
"insurances": {
"type": "hasMany",
"model": "CreditInsurance",
"foreignKey": "creditClassification"
}
}
}
}

View File

@ -10,11 +10,11 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"credit": {
"type": "Number"
"type": "number"
},
"created": {
"type": "date",
@ -23,7 +23,7 @@
}
},
"grade": {
"type": "Number"
"type": "number"
}
},
"relations": {

View File

@ -8,26 +8,26 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"description": "Identifier",
"id": true
},
"fiscalName": {
"type": "String",
"type": "string",
"required": true
},
"street": {
"type": "String"
"type": "string"
},
"nif": {
"type": "String",
"type": "string",
"required": true
},
"phone": {
"type": "String"
"type": "string"
},
"email": {
"type": "String"
"type": "string"
}
}
}

View File

@ -8,7 +8,7 @@
},
"properties": {
"freightPickUpPrice": {
"type": "Number"
"type": "number"
}
},
"acls": [{

View File

@ -9,14 +9,14 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"name": {
"type": "String"
"type": "string"
},
"code": {
"type": "String"
"type": "string"
}
},
"acls": [

View File

@ -14,15 +14,15 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"description": {
"type": "String",
"type": "string",
"required": true
},
"amount": {
"type": "Number",
"type": "number",
"required": true
},
"shipped": {
@ -32,7 +32,7 @@
"type": "date"
},
"greugeTypeFk": {
"type": "Number",
"type": "number",
"required": true
}

View File

@ -8,12 +8,12 @@
},
"properties": {
"code": {
"type": "String",
"type": "string",
"description": "Identifier",
"id": true
},
"name": {
"type": "String"
"type": "string"
}
},
"acls": [

View File

@ -9,11 +9,11 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"name": {
"type": "String"
"type": "string"
}
}
}

View File

@ -9,11 +9,11 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"code": {
"type": "String"
"type": "string"
},
"created": {
"type": "date"

View File

@ -9,15 +9,15 @@
"properties": {
"id": {
"id": true,
"type": "Number",
"type": "number",
"description": "Identifier"
},
"description": {
"type": "String",
"type": "string",
"required": true
},
"code": {
"type": "String",
"type": "string",
"required": true
}
},

View File

@ -8,7 +8,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
@ -23,7 +23,7 @@
"type": "string"
},
"outstandingDebt": {
"type": "Number"
"type": "number"
},
"isIbanRequiredForClients": {
"type": "boolean"

View File

@ -2,40 +2,40 @@
"name": "Recovery",
"base": "Loggable",
"log": {
"model": "ClientLog",
"relation": "client"
"model": "ClientLog",
"relation": "client"
},
"options": {
"mysql": {
"table": "recovery"
}
"mysql": {
"table": "recovery"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"started": {
"type": "date",
"required": true
},
"finished": {
"type": "date"
},
"amount": {
"type": "Number",
"required": true
},
"period": {
"type": "Number"
}
"id": {
"id": true,
"type": "number",
"description": "Identifier"
},
"started": {
"type": "date",
"required": true
},
"finished": {
"type": "date"
},
"amount": {
"type": "number",
"required": true
},
"period": {
"type": "number"
}
},
"relations": {
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
}
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
}
}
}
}

View File

@ -8,7 +8,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier",
"mysql": {

View File

@ -8,7 +8,7 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier",
"mysql": {

View File

@ -9,18 +9,18 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"uri": {
"type": "String"
"type": "string"
},
"apiKey": {
"type": "String"
"type": "string"
},
"title": {
"type": "String"
"type": "string"
}
}
}

View File

@ -9,30 +9,30 @@
},
"properties": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
"sender": {
"type": "String",
"type": "string",
"required": true
},
"destination": {
"type": "String",
"type": "string",
"required": true
},
"message": {
"type": "String",
"type": "string",
"required": true
},
"statusCode": {
"type": "Number"
"type": "number"
},
"status": {
"type": "String"
"type": "string"
},
"created": {
"type": "Date"
"type": "date"
}
},
"relations": {

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