Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3905-invoice-out_refund
This commit is contained in:
commit
0425b17b4e
|
@ -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') {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ module.exports = Self => {
|
|||
|
||||
const {data} = await Self.getUserStatus(recipient.name);
|
||||
if (data) {
|
||||
if (data.status === 'offline') {
|
||||
if (data.status === 'offline' || data.status === 'busy') {
|
||||
// Send message to department room
|
||||
const workerDepartment = await models.WorkerDepartment.findById(recipientId, {
|
||||
include: {
|
||||
|
@ -58,6 +58,8 @@ module.exports = Self => {
|
|||
|
||||
if (channelName)
|
||||
return Self.send(ctx, `#${channelName}`, `@${recipient.name} ➔ ${message}`);
|
||||
else
|
||||
return Self.send(ctx, `@${recipient.name}`, message);
|
||||
} else
|
||||
return Self.send(ctx, `@${recipient.name}`, message);
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('collectionFaults', {
|
||||
description: 'Update sale of a collection',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'shelvingFk',
|
||||
type: 'String',
|
||||
required: true,
|
||||
description: 'The shalving id'
|
||||
}, {
|
||||
arg: 'quantity',
|
||||
type: 'Number',
|
||||
required: true,
|
||||
description: 'The quantity to sale'
|
||||
}, {
|
||||
arg: 'itemFk',
|
||||
type: 'Number',
|
||||
required: true,
|
||||
description: 'The ticket id'
|
||||
}],
|
||||
returns: {
|
||||
type: 'Object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/collectionFaults`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.collectionFaults = async(shelvingFk, quantity, itemFk) => {
|
||||
query = `CALL vn.collection_faults(?,?,?)`;
|
||||
return await Self.rawSql(query, [shelvingFk, quantity, itemFk]);
|
||||
};
|
||||
};
|
|
@ -28,7 +28,7 @@ module.exports = Self => {
|
|||
const args = ctx.args;
|
||||
const models = Self.app.models;
|
||||
|
||||
const sale = await models.Sale.findById(args.saleId,);
|
||||
const sale = await models.Sale.findById(args.saleId);
|
||||
return await sale.updateAttribute('quantity', args.quantity);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
describe('collectionFaults()', () => {
|
||||
it('return shelving afected', async() => {
|
||||
let response = await app.models.Collection.collectionFaults('UXN', 0, 1);
|
||||
|
||||
expect(response.length).toBeGreaterThan(0);
|
||||
expect(response[0][0].shelvingFk).toEqual('UXN');
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -12,9 +12,9 @@ describe('docuware download()', () => {
|
|||
}
|
||||
};
|
||||
|
||||
const fileCabinetName = 'deliveryClientTest';
|
||||
const fileCabinetName = 'deliveryClient';
|
||||
const dialogDisplayName = 'find';
|
||||
const dialogName = 'findTest';
|
||||
const dialogName = 'findTicket';
|
||||
|
||||
const gotGetResponse = {
|
||||
body: JSON.stringify(
|
||||
|
|
|
@ -14,9 +14,9 @@ describe('docuware download()', () => {
|
|||
};
|
||||
|
||||
it('should return the downloaded file name', async() => {
|
||||
const fileCabinetName = 'deliveryClientTest';
|
||||
const fileCabinetName = 'deliveryClient';
|
||||
const dialogDisplayName = 'find';
|
||||
const dialogName = 'findTest';
|
||||
const dialogName = 'findTicket';
|
||||
const gotGetResponse = {
|
||||
body: JSON.stringify(
|
||||
{
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"type": "date"
|
||||
},
|
||||
"image": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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": [{
|
||||
|
|
|
@ -3,5 +3,4 @@ module.exports = Self => {
|
|||
require('../methods/collection/newCollection')(Self);
|
||||
require('../methods/collection/getSectors')(Self);
|
||||
require('../methods/collection/setSaleQuantity')(Self);
|
||||
require('../methods/collection/collectionFaults')(Self);
|
||||
};
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"code": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
},
|
||||
"expired": {
|
||||
"type": "date"
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"properties": {
|
||||
"userFk": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"email": {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"properties": {
|
||||
"code": {
|
||||
"id": true,
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier",
|
||||
"mysql": {
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"name": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"forceId": false
|
||||
},
|
||||
"username":{
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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/**/*"
|
||||
]
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO `salix`.`ACL`(`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES('ExpeditionState', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
|
@ -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');
|
|
@ -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');
|
|
@ -0,0 +1,14 @@
|
|||
create table `vn`.`invoiceOut_queue`
|
||||
(
|
||||
invoiceFk int(10) unsigned not null,
|
||||
queued datetime default now() not null,
|
||||
printed datetime null,
|
||||
`status` VARCHAR(50) default '' null,
|
||||
constraint invoiceOut_queue_pk
|
||||
primary key (invoiceFk),
|
||||
constraint invoiceOut_queue_invoiceOut_id_fk
|
||||
foreign key (invoiceFk) references invoiceOut (id)
|
||||
on update cascade on delete cascade
|
||||
)
|
||||
comment 'Queue for PDF invoicing';
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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 ;
|
|
@ -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 ;
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES ('Dms','deleteTrashFiles','WRITE','ALLOW','ROLE','employee')
|
|
@ -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();
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -56,27 +56,6 @@ INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossF
|
|||
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9
|
||||
FROM `vn`.`user`;
|
||||
|
||||
ALTER TABLE `vn`.`worker` ADD `originCountryFk` mediumint(8) unsigned NULL COMMENT 'País de origen';
|
||||
ALTER TABLE `vn`.`worker` ADD `educationLevelFk` SMALLINT NULL;
|
||||
ALTER TABLE `vn`.`worker` ADD `SSN` varchar(15) NULL;
|
||||
ALTER TABLE `vn`.`worker` CHANGE `maritalStatus__` `maritalStatus` enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
|
||||
ALTER TABLE `vn`.`worker` MODIFY COLUMN `maritalStatus` enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
|
||||
ALTER TABLE `vn`.`worker` CHANGE `maritalStatus` maritalStatus enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL AFTER sectorFk;
|
||||
ALTER TABLE `vn`.`worker` ADD CONSTRAINT `worker_FK_2` FOREIGN KEY (`educationLevelFk`) REFERENCES `vn`.`educationLevel`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE `vn`.`worker` ADD CONSTRAINT `worker_FK_1` FOREIGN KEY (`originCountryFk`) REFERENCES `vn`.`country`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
UPDATE `vn`.`worker` `w`
|
||||
SET `maritalStatus` = 'S';
|
||||
|
||||
UPDATE `vn`.`worker` `w`
|
||||
SET `originCountryFk` = '1';
|
||||
|
||||
UPDATE `vn`.`worker` `w`
|
||||
SET `educationLevelFk` = '2';
|
||||
|
||||
UPDATE `vn`.`worker` `w`
|
||||
SET `SSN` = '123456789123';
|
||||
|
||||
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
|
||||
UPDATE `vn`.`worker` SET bossFk = 20 WHERE id = 1 OR id = 9;
|
||||
UPDATE `vn`.`worker` SET bossFk = 19 WHERE id = 18;
|
||||
|
@ -147,15 +126,6 @@ INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`,
|
|||
(19,'Francia', 1, 'FR', 1, 27, 4, 0, 1),
|
||||
(30,'Canarias', 1, 'IC', 1, 24, 4, 1, 2);
|
||||
|
||||
INSERT INTO `hedera`.`language` (`code`, `name`, `orgName`, `isActive`)
|
||||
VALUES
|
||||
('ca', 'Català' , 'Catalan' , TRUE),
|
||||
('en', 'English' , 'English' , TRUE),
|
||||
('es', 'Español' , 'Spanish' , TRUE),
|
||||
('fr', 'Français' , 'French' , TRUE),
|
||||
('mn', 'Португалий', 'Mongolian' , TRUE),
|
||||
('pt', 'Português' , 'Portuguese', TRUE);
|
||||
|
||||
INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
|
||||
VALUES
|
||||
(1, 'Main Warehouse'),
|
||||
|
@ -182,8 +152,9 @@ INSERT INTO `vn`.`parking` (`id`, `column`, `row`, `sectorFk`, `code`, `pickingO
|
|||
|
||||
INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `isPrinted`, `priority`, `parked`, `userFk`)
|
||||
VALUES
|
||||
('GVC', '1', '0', '1', '0', '1106'),
|
||||
('HEJ', '2', '0', '1', '0', '1106');
|
||||
('GVC', 1, 0, 1, 0, 1106),
|
||||
('HEJ', 2, 0, 1, 0, 1106),
|
||||
('UXN', 1, 0, 1, 0, 1106);
|
||||
|
||||
INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`,`code`, `maxAmount`)
|
||||
VALUES
|
||||
|
@ -342,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
|
||||
|
@ -422,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());
|
||||
|
@ -883,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
|
||||
|
@ -1078,10 +1066,11 @@ INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
|
|||
(32, 36, -92.324),
|
||||
(32, 39, 0.994);
|
||||
|
||||
INSERT INTO `vn`.`itemShelving` (`id`, `itemFk`, `shelvingFk`, `shelve`, `deep`, `quantity`, `visible`, `available`, `grouping`, `packing`, `level`, `userFk`)
|
||||
INSERT INTO `vn`.`itemShelving` (`itemFk`, `shelvingFk`, `shelve`, `visible`, `grouping`, `packing`, `userFk`)
|
||||
VALUES
|
||||
('1', '2', 'GVC', 'A', '0', '1', '1', '1', '1', '1', '1', '1106'),
|
||||
('2', '4', 'HEJ', 'A', '0', '2', '1', '1', '1', '1', '1', '1106');
|
||||
(2, 'GVC', 'A', 1, 1, 1, 1106),
|
||||
(4, 'HEJ', 'A', 1, 1, 1, 1106),
|
||||
(1, 'UXN', 'A', 2, 12, 12, 1106);
|
||||
|
||||
INSERT INTO `vn`.`itemShelvingSale` (`itemShelvingFk`, `saleFk`, `quantity`, `created`, `userFk`)
|
||||
VALUES
|
||||
|
@ -1135,14 +1124,6 @@ INSERT INTO `vn`.`parking` (`column`, `row`, `sectorFk`, `code`, `pickingOrder`)
|
|||
VALUES
|
||||
('100', '01', 1, '100-01', 1);
|
||||
|
||||
INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `priority`, `userFk`)
|
||||
VALUES
|
||||
('UXN', 1, 1, 1106);
|
||||
|
||||
INSERT INTO `vn`.`itemShelving` (`itemFk`, `shelvingFk`, `shelve`, `deep`, `quantity`, `visible`, `available`, `grouping`, `packing`, `level`, `userFk`)
|
||||
VALUES
|
||||
(1, 'UXN', 'A', 2, 12, 12, 12, 12, 12, 1, 1106);
|
||||
|
||||
INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `level`)
|
||||
VALUES
|
||||
(1, 1, 1);
|
||||
|
@ -1332,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
|
||||
|
@ -2266,13 +2247,19 @@ INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `c
|
|||
|
||||
INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `contentType`, `workerFk`, `warehouseFk`, `companyFk`, `hardCopyNumber`, `hasFile`, `reference`, `description`, `created`)
|
||||
VALUES
|
||||
(1, 14, '1.txt', 'text/plain', 5, 1, 442, NULL, FALSE, 'Ticket:11', 'Ticket:11 dms for the ticket', CURDATE()),
|
||||
(2, 5, '2.txt', 'text/plain', 5, 1, 442, 1, TRUE, 'Client:104', 'Client:104 dms for the client', CURDATE()),
|
||||
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', CURDATE()),
|
||||
(4, 3, '4.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Worker: 106', 'Worker:106 readme', CURDATE()),
|
||||
(5, 5, '5.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'travel: 1', 'dmsForThermograph', CURDATE()),
|
||||
(6, 5, '6.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'NotExists', 'DoesNotExists', CURDATE());
|
||||
(1, 14, '1.txt', 'text/plain', 5, 1, 442, NULL, FALSE, 'Ticket:11', 'Ticket:11 dms for the ticket', CURDATE()),
|
||||
(2, 5, '2.txt', 'text/plain', 5, 1, 442, 1, TRUE, 'Client:104', 'Client:104 dms for the client', CURDATE()),
|
||||
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', CURDATE()),
|
||||
(4, 3, '4.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Worker: 106', 'Worker:106 readme', CURDATE()),
|
||||
(5, 5, '5.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'travel: 1', 'dmsForThermograph', CURDATE()),
|
||||
(6, 5, '6.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'NotExists', 'DoesNotExists', CURDATE()),
|
||||
(7, 20, '7.jpg', 'image/jpeg', 9, 1, 442, NULL, FALSE, '1', 'TICKET ID DEL CLIENTE BRUCE WAYNE ID 1101', CURDATE()),
|
||||
(8, 20, '8.mp4', 'video/mp4', 9, 1, 442, NULL, FALSE, '1', 'TICKET ID DEL CLIENTE BRUCE WAYNE ID 1101', CURDATE());
|
||||
|
||||
INSERT INTO `vn`.`claimDms`(`claimFk`, `dmsFk`)
|
||||
VALUES
|
||||
(1, 7),
|
||||
(1, 8);
|
||||
|
||||
INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`)
|
||||
VALUES
|
||||
|
@ -2532,7 +2519,7 @@ INSERT INTO `bs`.`sale` (`saleFk`, `amount`, `dated`, `typeFk`, `clientFk`)
|
|||
|
||||
INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`)
|
||||
VALUES
|
||||
('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word');
|
||||
('deliveryClient', 'deliveryClient', 'findTicket', 'word');
|
||||
|
||||
INSERT INTO `vn`.`docuwareConfig` (`url`)
|
||||
VALUES
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,6 +14,8 @@ echo "" > "$DUMPED_FILE"
|
|||
TABLES=(
|
||||
util
|
||||
config
|
||||
version
|
||||
versionLog
|
||||
)
|
||||
dump_tables ${TABLES[@]}
|
||||
|
||||
|
@ -74,10 +76,20 @@ dump_tables ${TABLES[@]}
|
|||
|
||||
TABLES=(
|
||||
hedera
|
||||
browser
|
||||
imageCollection
|
||||
imageCollectionSize
|
||||
language
|
||||
link
|
||||
location
|
||||
menu
|
||||
message
|
||||
metatag
|
||||
newsTag
|
||||
restPriv
|
||||
social
|
||||
tpvError
|
||||
tpvResponse
|
||||
imageCollectionSize
|
||||
|
||||
)
|
||||
dump_tables ${TABLES[@]}
|
||||
|
|
|
@ -49,6 +49,7 @@ IGNORETABLES=(
|
|||
--ignore-table=vn.grantGroup
|
||||
--ignore-table=vn.invoiceCorrection__
|
||||
--ignore-table=vn.itemTaxCountrySpain
|
||||
--ignore-table=vn.itemShelvingPlacementSupplyStock__
|
||||
--ignore-table=vn.itemFreeNumber__
|
||||
--ignore-table=vn.mail__
|
||||
--ignore-table=vn.manaSpellers
|
||||
|
|
|
@ -731,7 +731,7 @@ export default {
|
|||
claimAction: {
|
||||
importClaimButton: 'vn-claim-action vn-button[label="Import claim"]',
|
||||
anyLine: 'vn-claim-action vn-tbody > vn-tr',
|
||||
firstDeleteLine: 'vn-claim-action vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
|
||||
firstDeleteLine: 'vn-claim-action tr:nth-child(1) vn-icon-button[icon="delete"]',
|
||||
isPaidWithManaCheckbox: 'vn-claim-action vn-check[ng-model="$ctrl.claim.isChargedToMana"]'
|
||||
},
|
||||
ordersIndex: {
|
||||
|
@ -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"]',
|
||||
|
@ -1133,7 +1133,7 @@ export default {
|
|||
entryLatestBuys: {
|
||||
firstBuy: 'vn-entry-latest-buys tbody > tr:nth-child(1)',
|
||||
allBuysCheckBox: 'vn-entry-latest-buys thead vn-check',
|
||||
secondBuyCheckBox: 'vn-entry-latest-buys tbody tr:nth-child(2) vn-check[ng-model="buy.$checked"]',
|
||||
secondBuyCheckBox: 'vn-entry-latest-buys tbody tr:nth-child(2) vn-check[ng-model="buy.checked"]',
|
||||
editBuysButton: 'vn-entry-latest-buys vn-button[icon="edit"]',
|
||||
fieldAutocomplete: 'vn-autocomplete[ng-model="$ctrl.editedColumn.field"]',
|
||||
newValueInput: 'vn-textfield[ng-model="$ctrl.editedColumn.newValue"]',
|
||||
|
|
|
@ -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();
|
|
@ -111,7 +111,7 @@ describe('Client lock verified data path', () => {
|
|||
await page.waitToClick(selectors.clientFiscalData.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain(`You can't make changes on a client with verified data`);
|
||||
expect(message.text).toContain(`Not enough privileges to edit a client with verified data`);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -123,19 +123,19 @@ describe('Client lock verified data path', () => {
|
|||
await page.accessToSection('client.card.fiscalData');
|
||||
}, 20000);
|
||||
|
||||
it('should confirm verified data button is enabled for salesAssistant', async() => {
|
||||
it('should confirm verified data button is disabled for salesAssistant', async() => {
|
||||
const isDisabled = await page.isDisabled(selectors.clientFiscalData.verifiedDataCheckbox);
|
||||
|
||||
expect(isDisabled).toBeFalsy();
|
||||
expect(isDisabled).toBeTrue();
|
||||
});
|
||||
|
||||
it('should now edit the social name', async() => {
|
||||
it('should return error when edit the social name', async() => {
|
||||
await page.clearInput(selectors.clientFiscalData.socialName);
|
||||
await page.write(selectors.clientFiscalData.socialName, 'new social name edition');
|
||||
await page.waitToClick(selectors.clientFiscalData.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Data saved!');
|
||||
expect(message.text).toContain(`Not enough privileges to edit a client with verified data`);
|
||||
});
|
||||
|
||||
it('should now confirm the social name have been edited once and for all', async() => {
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
SelectAllRows: Select the {{rows}} row(s)
|
|
@ -0,0 +1,3 @@
|
|||
SelectAllRows: Seleccionar las {{rows}} fila(s)
|
||||
All: Se han seleccionado
|
||||
row(s) have been selected.: fila(s).
|
|
@ -3,3 +3,24 @@
|
|||
indeterminate="$ctrl.isIndeterminate"
|
||||
translate-attr="{title: 'Check all'}">
|
||||
</vn-check>
|
||||
<vn-icon-button
|
||||
class="vn-pl-none"
|
||||
ng-if="$ctrl.isCheckedDummy()"
|
||||
icon="expand_more"
|
||||
vn-popover="menu"
|
||||
ng-click="$ctrl.countRows()">
|
||||
</vn-icon-button>
|
||||
<vn-menu
|
||||
vn-id="menu"
|
||||
ng-if="$ctrl.isCheckedDummy()">
|
||||
<vn-list>
|
||||
<span translate>All</span>
|
||||
<span class="bold">
|
||||
{{$ctrl.rows}}
|
||||
</span>
|
||||
<span translate>row(s) have been selected.</span>
|
||||
<span class="bold link" ng-click="$ctrl.checkDummy()">
|
||||
{{$ctrl.allRowsText}}
|
||||
</span>
|
||||
</vn-list>
|
||||
</vn-menu>
|
|
@ -106,6 +106,9 @@ export default class MultiCheck extends FormInput {
|
|||
|
||||
this.toggle();
|
||||
this.emit('change', value);
|
||||
|
||||
if (!value)
|
||||
this.checkedDummyCount = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,12 +135,47 @@ export default class MultiCheck extends FormInput {
|
|||
areAllUnchecked() {
|
||||
if (!this.model || !this.model.data) return;
|
||||
|
||||
this.checkedDummyCount = null;
|
||||
const data = this.model.data;
|
||||
return data.every(item => {
|
||||
return item[this.checkField] === false;
|
||||
});
|
||||
}
|
||||
|
||||
countRows() {
|
||||
if (!this.model || !this.model.data) return;
|
||||
|
||||
const data = this.model.data;
|
||||
const modelParams = this.model.userParams;
|
||||
const params = {
|
||||
filter: {
|
||||
modelParams: modelParams,
|
||||
limit: null
|
||||
}
|
||||
};
|
||||
|
||||
this.rows = data.length;
|
||||
|
||||
this.$http.get(this.model.url, {params})
|
||||
.then(res => {
|
||||
this.allRowsCount = res.data.length;
|
||||
this.allRowsText = this.$t('SelectAllRows', {
|
||||
rows: this.allRowsCount
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
checkDummy() {
|
||||
if (this.checkedDummyCount)
|
||||
return this.checkedDummyCount = null;
|
||||
|
||||
this.checkedDummyCount = this.allRowsCount;
|
||||
}
|
||||
|
||||
isCheckedDummy() {
|
||||
return this.checked && this.checkDummyEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles checked property on
|
||||
* all instances
|
||||
|
@ -158,7 +196,9 @@ ngModule.vnComponent('vnMultiCheck', {
|
|||
checkField: '@?',
|
||||
checkAll: '=?',
|
||||
checked: '=?',
|
||||
disabled: '<?'
|
||||
disabled: '<?',
|
||||
checkDummyEnabled: '<?',
|
||||
checkedDummyCount: '=?'
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -4,10 +4,14 @@ import crudModel from 'core/mocks/crud-model';
|
|||
describe('Component vnMultiCheck', () => {
|
||||
let controller;
|
||||
let $element;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('vnCore'));
|
||||
|
||||
beforeEach(inject($componentController => {
|
||||
beforeEach(inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
$element = angular.element(`<div class="shown"></div>`);
|
||||
controller = $componentController('vnMultiCheck', {$element: $element});
|
||||
controller._model = crudModel;
|
||||
|
@ -26,6 +30,14 @@ describe('Component vnMultiCheck', () => {
|
|||
expect(controller._checked).toEqual(crudModel);
|
||||
expect(controller.toggle).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should set checkedDummyCount to null`, () => {
|
||||
jest.spyOn(controller, 'toggle');
|
||||
controller.checkedDummyCount = 12;
|
||||
controller.checked = null;
|
||||
|
||||
expect(controller.checkedDummyCount).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggle()', () => {
|
||||
|
@ -132,4 +144,76 @@ describe('Component vnMultiCheck', () => {
|
|||
expect(thirdRow.checked).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('countRows()', () => {
|
||||
it(`should count visible rows and all rows of model`, () => {
|
||||
controller.model.url = 'modelUrl/filter';
|
||||
const data = controller.model.data;
|
||||
const filter = {
|
||||
limit: null
|
||||
};
|
||||
const serializedParams = $httpParamSerializer({filter});
|
||||
|
||||
const response = [
|
||||
{id: 1, name: 'My item 1'},
|
||||
{id: 2, name: 'My item 2'},
|
||||
{id: 3, name: 'My item 3'},
|
||||
{id: 4, name: 'My item 4'},
|
||||
{id: 5, name: 'My item 5'},
|
||||
{id: 6, name: 'My item 6'}
|
||||
];
|
||||
|
||||
controller.countRows();
|
||||
$httpBackend.expectGET(`modelUrl/filter?${serializedParams}`).respond(response);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.rows).toEqual(data.length);
|
||||
expect(controller.allRowsCount).toEqual(response.length);
|
||||
expect(controller.allRowsCount).toBeGreaterThan(controller.rows);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkDummy()', () => {
|
||||
const allRows = 1234;
|
||||
it(`should set the checked dummy count to all rows count if there was no count yet`, () => {
|
||||
controller.checkedDummyCount = null;
|
||||
controller.allRowsCount = allRows;
|
||||
controller.checkDummy();
|
||||
|
||||
expect(controller.checkedDummyCount).toEqual(controller.allRowsCount);
|
||||
});
|
||||
|
||||
it(`should remove the dummy count if there was an existing one`, () => {
|
||||
controller.checkedDummyCount = allRows;
|
||||
controller.checkDummy();
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
@import "variables";
|
||||
vn-multi-check {
|
||||
.vn-check {
|
||||
margin-bottom: 12px
|
||||
}
|
||||
}
|
||||
|
||||
.bold{
|
||||
font-weight: bold;
|
||||
}
|
|
@ -26,7 +26,7 @@
|
|||
.icon-agency-term:before {
|
||||
content: "\e950";
|
||||
}
|
||||
.icon-deaulter:before {
|
||||
.icon-defaulter:before {
|
||||
content: "\e94b";
|
||||
}
|
||||
.icon-100:before {
|
||||
|
|
189
gulpfile.js
189
gulpfile.js
|
@ -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
|
||||
};
|
||||
|
|
|
@ -47,5 +47,6 @@ module.exports = {
|
|||
'^.+\\.js?$': 'babel-jest',
|
||||
'^.+\\.html$': 'html-loader-jest'
|
||||
},
|
||||
reporters: ['default', 'jest-junit']
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
"That payment method requires an IBAN": "That payment method requires an IBAN",
|
||||
"That payment method requires a BIC": "That payment method requires a BIC",
|
||||
"The default consignee can not be unchecked": "The default consignee can not be unchecked",
|
||||
"You can't make changes on a client with verified data": "You can't make changes on a client with verified data",
|
||||
"Enter an integer different to zero": "Enter an integer different to zero",
|
||||
"Package cannot be blank": "Package cannot be blank",
|
||||
"The new quantity should be smaller than the old one": "The new quantity should be smaller than the old one",
|
||||
|
@ -123,5 +122,6 @@
|
|||
"The type of business must be filled in basic data": "The type of business must be filled in basic data",
|
||||
"The worker has hours recorded that day": "The worker has hours recorded that day",
|
||||
"isWithoutNegatives": "isWithoutNegatives",
|
||||
"routeFk": "routeFk"
|
||||
"routeFk": "routeFk",
|
||||
"Not enough privileges to edit a client with verified data": "Not enough privileges to edit a client with verified data"
|
||||
}
|
|
@ -50,7 +50,7 @@
|
|||
"You don't have enough privileges to change that field": "No tienes permisos para cambiar ese campo",
|
||||
"Warehouse cannot be blank": "El almacén no puede quedar en blanco",
|
||||
"Agency cannot be blank": "La agencia no puede quedar en blanco",
|
||||
"You can't make changes on a client with verified data": "No puedes hacer cambios en un cliente con datos comprobados",
|
||||
"Not enough privileges to edit a client with verified data": "No tienes permisos para hacer cambios en un cliente con datos comprobados",
|
||||
"This address doesn't exist": "Este consignatario no existe",
|
||||
"You must delete the claim id %d first": "Antes debes borrar la reclamación %d",
|
||||
"You don't have enough privileges": "No tienes suficientes permisos",
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
"multipart/x-zip",
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg"
|
||||
"image/jpg",
|
||||
"video/mp4"
|
||||
]
|
||||
},
|
||||
"dmsStorage": {
|
||||
|
@ -84,5 +85,18 @@
|
|||
"application/octet-stream",
|
||||
"application/pdf"
|
||||
]
|
||||
},
|
||||
"claimStorage": {
|
||||
"name": "claimStorage",
|
||||
"connector": "loopback-component-storage",
|
||||
"provider": "filesystem",
|
||||
"root": "./storage/dms",
|
||||
"maxFileSize": "31457280",
|
||||
"allowedContentTypes": [
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg",
|
||||
"video/mp4"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"verifyCert": {
|
||||
"type": "Boolean"
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('deleteClamedSales', {
|
||||
description: 'Deletes the claimed sales',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'sales',
|
||||
type: ['object'],
|
||||
required: true,
|
||||
description: 'The sales to remove'
|
||||
}],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/deleteClamedSales`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.deleteClamedSales = async(ctx, sales, options) => {
|
||||
const models = Self.app.models;
|
||||
const myOptions = {};
|
||||
const tx = await Self.beginTransaction({});
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction)
|
||||
myOptions.transaction = tx;
|
||||
|
||||
try {
|
||||
const promises = [];
|
||||
for (let sale of sales) {
|
||||
const deletedSale = models.ClaimEnd.destroyById(sale.id, myOptions);
|
||||
promises.push(deletedSale);
|
||||
}
|
||||
|
||||
const deletedSales = await Promise.all(promises);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return deletedSales;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
|
||||
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: `If it's and integer searchs by id, otherwise it searchs by client id`,
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/filter`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.filter = async(ctx, filter, options) => {
|
||||
const conn = Self.dataSource.connector;
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const stmts = [];
|
||||
|
||||
const stmt = new ParameterizedSQL(
|
||||
`SELECT *
|
||||
FROM (
|
||||
SELECT
|
||||
ce.id,
|
||||
ce.claimFk,
|
||||
s.itemFk,
|
||||
s.ticketFk,
|
||||
ce.claimDestinationFk,
|
||||
t.landed,
|
||||
s.quantity,
|
||||
s.concept,
|
||||
s.price,
|
||||
s.discount,
|
||||
s.quantity * s.price * ((100 - s.discount) / 100) total
|
||||
FROM vn.claimEnd ce
|
||||
LEFT JOIN vn.sale s ON s.id = ce.saleFk
|
||||
LEFT JOIN vn.ticket t ON t.id = s.ticketFk
|
||||
) ce`
|
||||
);
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
const itemsIndex = stmts.push(stmt) - 1;
|
||||
|
||||
const sql = ParameterizedSQL.join(stmts, ';');
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
|
||||
return itemsIndex === 0 ? result : result[itemsIndex];
|
||||
};
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('downloadFile', {
|
||||
description: 'Get the claim file',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
description: 'The document id',
|
||||
http: {source: 'path'}
|
||||
}
|
||||
],
|
||||
returns: [
|
||||
{
|
||||
arg: 'body',
|
||||
type: 'file',
|
||||
root: true
|
||||
},
|
||||
{
|
||||
arg: 'Content-Type',
|
||||
type: 'String',
|
||||
http: {target: 'header'}
|
||||
},
|
||||
{
|
||||
arg: 'Content-Disposition',
|
||||
type: 'String',
|
||||
http: {target: 'header'}
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: `/:id/downloadFile`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.downloadFile = async function(ctx, id) {
|
||||
const models = Self.app.models;
|
||||
const ClaimContainer = models.ClaimContainer;
|
||||
const dms = await models.Dms.findById(id);
|
||||
const pathHash = ClaimContainer.getHash(dms.id);
|
||||
try {
|
||||
await ClaimContainer.getFile(pathHash, dms.file);
|
||||
} catch (e) {
|
||||
if (e.code != 'ENOENT')
|
||||
throw e;
|
||||
|
||||
const error = new UserError(`File doesn't exists`);
|
||||
error.statusCode = 404;
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
const stream = ClaimContainer.downloadStream(pathHash, dms.file);
|
||||
|
||||
return [stream, dms.contentType, `filename="${dms.file}"`];
|
||||
};
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('claim downloadFile()', () => {
|
||||
const dmsId = 7;
|
||||
|
||||
it('should return a response for an employee with image content-type', async() => {
|
||||
const workerId = 1107;
|
||||
const ctx = {req: {accessToken: {userId: workerId}}};
|
||||
const result = await app.models.Claim.downloadFile(ctx, dmsId);
|
||||
|
||||
expect(result[1]).toEqual('image/jpeg');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('claim uploadFile()', () => {
|
||||
it(`should return an error for a user without enough privileges`, async() => {
|
||||
const clientId = 1101;
|
||||
const ticketDmsTypeId = 14;
|
||||
const ctx = {req: {accessToken: {userId: clientId}}, args: {dmsTypeId: ticketDmsTypeId}};
|
||||
|
||||
let error;
|
||||
await app.models.Claim.uploadFile(ctx).catch(e => {
|
||||
error = e;
|
||||
}).finally(() => {
|
||||
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||
});
|
||||
|
||||
expect(error).toBeDefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('updateClaimDestination', {
|
||||
description: 'Update a claim with privileges',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'rows',
|
||||
type: ['object'],
|
||||
required: true,
|
||||
description: `the sales which will be modified the claimDestinationFk`
|
||||
}, {
|
||||
arg: 'claimDestinationFk',
|
||||
type: 'number',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/updateClaimDestination`,
|
||||
verb: 'post'
|
||||
}
|
||||
});
|
||||
|
||||
Self.updateClaimDestination = async(rows, claimDestinationFk, 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 promises = [];
|
||||
for (let row of rows) {
|
||||
const claimEnd = await models.ClaimEnd.findById(row.id, null, myOptions);
|
||||
const updatedClaimEnd = claimEnd.updateAttribute('claimDestinationFk', claimDestinationFk, myOptions);
|
||||
promises.push(updatedClaimEnd);
|
||||
}
|
||||
|
||||
const updatedSales = await Promise.all(promises);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return updatedSales;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,6 +1,10 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('uploadFile', {
|
||||
description: 'Upload and attach a document',
|
||||
description: 'Upload and attach a file',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
|
@ -53,22 +57,54 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.uploadFile = async(ctx, id, options) => {
|
||||
let tx;
|
||||
const tx = await Self.beginTransaction({});
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
if (!myOptions.transaction)
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
const models = Self.app.models;
|
||||
const promises = [];
|
||||
const TempContainer = models.TempContainer;
|
||||
const ClaimContainer = models.ClaimContainer;
|
||||
const fileOptions = {};
|
||||
const args = ctx.args;
|
||||
|
||||
let srcFile;
|
||||
try {
|
||||
const uploadedFiles = await models.Dms.uploadFile(ctx, myOptions);
|
||||
uploadedFiles.forEach(dms => {
|
||||
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId, myOptions);
|
||||
if (!hasWriteRole)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
// Upload file to temporary path
|
||||
const tempContainer = await TempContainer.container('dms');
|
||||
const uploaded = await TempContainer.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
||||
const files = Object.values(uploaded.files).map(file => {
|
||||
return file[0];
|
||||
});
|
||||
|
||||
const addedDms = [];
|
||||
for (const uploadedFile of files) {
|
||||
const newDms = await createDms(ctx, uploadedFile, myOptions);
|
||||
const pathHash = ClaimContainer.getHash(newDms.id);
|
||||
|
||||
const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name);
|
||||
srcFile = path.join(file.client.root, file.container, file.name);
|
||||
|
||||
const claimContainer = await ClaimContainer.container(pathHash);
|
||||
const dstFile = path.join(claimContainer.client.root, pathHash, newDms.file);
|
||||
|
||||
await fs.move(srcFile, dstFile, {
|
||||
overwrite: true
|
||||
});
|
||||
|
||||
addedDms.push(newDms);
|
||||
}
|
||||
|
||||
addedDms.forEach(dms => {
|
||||
const newClaimDms = models.ClaimDms.create({
|
||||
claimFk: id,
|
||||
dmsFk: dms.id
|
||||
|
@ -83,7 +119,34 @@ module.exports = Self => {
|
|||
return resolvedPromises;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
|
||||
if (fs.existsSync(srcFile))
|
||||
await fs.unlink(srcFile);
|
||||
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
async function createDms(ctx, file, myOptions) {
|
||||
const models = Self.app.models;
|
||||
const myUserId = ctx.req.accessToken.userId;
|
||||
const args = ctx.args;
|
||||
|
||||
const newDms = await models.Dms.create({
|
||||
workerFk: myUserId,
|
||||
dmsTypeFk: args.dmsTypeId,
|
||||
companyFk: args.companyId,
|
||||
warehouseFk: args.warehouseId,
|
||||
reference: args.reference,
|
||||
description: args.description,
|
||||
contentType: file.type,
|
||||
hasFile: args.hasFile
|
||||
}, myOptions);
|
||||
|
||||
let fileName = file.name;
|
||||
const extension = models.DmsContainer.getFileExtension(fileName);
|
||||
fileName = `${newDms.id}.${extension}`;
|
||||
|
||||
return newDms.updateAttribute('file', fileName, myOptions);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -37,5 +37,8 @@
|
|||
},
|
||||
"ClaimLog": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ClaimContainer": {
|
||||
"dataSource": "claimStorage"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"quantity": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "ClaimContainer",
|
||||
"base": "Container",
|
||||
"acls": [{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}]
|
||||
}
|
|
@ -8,12 +8,12 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"description": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
],
|
||||
"properties": {
|
||||
"dmsFk": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"required": true
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/claim-end/filter')(Self);
|
||||
require('../methods/claim-end/deleteClamedSales')(Self);
|
||||
};
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
}
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"description": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"description": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"description": {
|
||||
"type": "String"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
|
|
|
@ -7,4 +7,6 @@ module.exports = Self => {
|
|||
require('../methods/claim/uploadFile')(Self);
|
||||
require('../methods/claim/updateClaimAction')(Self);
|
||||
require('../methods/claim/isEditable')(Self);
|
||||
require('../methods/claim/updateClaimDestination')(Self);
|
||||
require('../methods/claim/downloadFile')(Self);
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
<vn-crud-model vn-id="model"
|
||||
url="ClaimEnds"
|
||||
filter="$ctrl.filter"
|
||||
url="ClaimEnds/filter"
|
||||
link="{claimFk: $ctrl.$params.id}"
|
||||
data="$ctrl.salesClaimed"
|
||||
auto-load="true"
|
||||
auto-save="true"
|
||||
on-save="$ctrl.onSave()">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
|
@ -19,101 +17,124 @@
|
|||
</vn-label-value>
|
||||
</vn-card>
|
||||
<vn-card class="vn-pa-lg vn-w-lg">
|
||||
<section class="header">
|
||||
<vn-tool-bar class="vn-mb-md">
|
||||
<vn-button
|
||||
label="Import claim"
|
||||
disabled="$ctrl.claim.claimStateFk == $ctrl.resolvedStateId"
|
||||
vn-http-click="$ctrl.importToNewRefundTicket()"
|
||||
translate-attr="{title: 'Imports claim details'}">
|
||||
</vn-button>
|
||||
<vn-range
|
||||
label="Responsability"
|
||||
min-label="Company"
|
||||
max-label="Sales/Client"
|
||||
ng-model="$ctrl.claim.responsibility"
|
||||
max="$ctrl.maxResponsibility"
|
||||
min="1"
|
||||
step="1"
|
||||
on-change="$ctrl.save({responsibility: value})">
|
||||
</vn-range>
|
||||
</vn-tool-bar>
|
||||
<vn-check vn-one
|
||||
label="Is paid with mana"
|
||||
ng-model="$ctrl.claim.isChargedToMana"
|
||||
on-change="$ctrl.save({isChargedToMana: value})">
|
||||
</vn-check>
|
||||
</section>
|
||||
<vn-data-viewer model="model">
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th number>Id</vn-th>
|
||||
<vn-th number>Ticket</vn-th>
|
||||
<vn-th>Destination</vn-th>
|
||||
<vn-th expand>Landed</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
<vn-th>Description</vn-th>
|
||||
<vn-th number>Price</vn-th>
|
||||
<vn-th number>Disc.</vn-th>
|
||||
<vn-th number>Total</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr
|
||||
<smart-table
|
||||
model="model"
|
||||
options="$ctrl.smartTableOptions"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
<slot-actions>
|
||||
<section class="header">
|
||||
<vn-tool-bar class="vn-mb-md">
|
||||
<vn-button
|
||||
label="Import claim"
|
||||
disabled="$ctrl.claim.claimStateFk == $ctrl.resolvedStateId"
|
||||
vn-http-click="$ctrl.importToNewRefundTicket()"
|
||||
translate-attr="{title: 'Imports claim details'}">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
label="Change destination"
|
||||
disabled="$ctrl.checked.length == 0"
|
||||
ng-click="changeDestination.show()">
|
||||
</vn-button>
|
||||
<vn-range
|
||||
label="Responsability"
|
||||
min-label="Company"
|
||||
max-label="Sales/Client"
|
||||
ng-model="$ctrl.claim.responsibility"
|
||||
max="$ctrl.maxResponsibility"
|
||||
min="1"
|
||||
step="1"
|
||||
on-change="$ctrl.save({responsibility: value})">
|
||||
</vn-range>
|
||||
</vn-tool-bar>
|
||||
<vn-check class="right"
|
||||
vn-one
|
||||
label="Is paid with mana"
|
||||
ng-model="$ctrl.claim.isChargedToMana"
|
||||
on-change="$ctrl.save({isChargedToMana: value})">
|
||||
</vn-check>
|
||||
</section>
|
||||
</slot-actions>
|
||||
<slot-table>
|
||||
<table model="model">
|
||||
<thead>
|
||||
<tr>
|
||||
<th shrink>
|
||||
<vn-multi-check
|
||||
model="model"
|
||||
check-field="$checked">
|
||||
</vn-multi-check>
|
||||
</th>
|
||||
<th number field="itemFk">Id</th>
|
||||
<th number field="ticketFk">Ticket</th>
|
||||
<th field="claimDestinationFk">Destination</th>
|
||||
<th expand field="landed">Landed</th>
|
||||
<th number field="quantity">Quantity</th>
|
||||
<th field="concept">Description</th>
|
||||
<th number field="price">Price</th>
|
||||
<th number field="discount">Disc.</th>
|
||||
<th number field="total">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
ng-repeat="saleClaimed in $ctrl.salesClaimed"
|
||||
vn-repeat-last on-last="$ctrl.focusLastInput()">
|
||||
<vn-td number>
|
||||
<span
|
||||
ng-click="itemDescriptor.show($event, saleClaimed.sale.itemFk)"
|
||||
<td>
|
||||
<vn-check
|
||||
ng-model="saleClaimed.$checked"
|
||||
vn-click-stop>
|
||||
</vn-check>
|
||||
</td>
|
||||
<td number>
|
||||
<vn-span
|
||||
ng-click="itemDescriptor.show($event, saleClaimed.itemFk)"
|
||||
class="link">
|
||||
{{::saleClaimed.sale.itemFk | zeroFill:6}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>
|
||||
<span
|
||||
{{::saleClaimed.itemFk | zeroFill:6}}
|
||||
</vn-span>
|
||||
</td>
|
||||
<td number>
|
||||
<vn-span
|
||||
class="link"
|
||||
ng-click="ticketDescriptor.show($event, saleClaimed.sale.ticketFk)">
|
||||
{{::saleClaimed.sale.ticketFk}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>
|
||||
ng-click="ticketDescriptor.show($event, saleClaimed.ticketFk)">
|
||||
{{::saleClaimed.ticketFk}}
|
||||
</vn-span>
|
||||
</td>
|
||||
<td expand>
|
||||
<vn-autocomplete vn-one id="claimDestinationFk"
|
||||
ng-model="saleClaimed.claimDestinationFk"
|
||||
data="claimDestinations"
|
||||
on-change="$ctrl.updateDestination(saleClaimed, value)"
|
||||
fields="['id','description']"
|
||||
value-field="id"
|
||||
show-field="description">
|
||||
</vn-autocomplete>
|
||||
</vn-td>
|
||||
<vn-td expand>{{::saleClaimed.sale.ticket.landed | date: 'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td number>{{::saleClaimed.sale.quantity}}</vn-td>
|
||||
<vn-td expand>{{::saleClaimed.sale.concept}}</vn-td>
|
||||
<vn-td number>{{::saleClaimed.sale.price | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::saleClaimed.sale.discount}} %</vn-td>
|
||||
<vn-td number>
|
||||
{{saleClaimed.sale.quantity * saleClaimed.sale.price *
|
||||
((100 - saleClaimed.sale.discount) / 100) | currency: 'EUR':2}}
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
</td>
|
||||
<td expand>{{::saleClaimed.landed | date: 'dd/MM/yyyy'}}</td>
|
||||
<td number>{{::saleClaimed.quantity}}</td>
|
||||
<td expand>{{::saleClaimed.concept}}</td>
|
||||
<td number>{{::saleClaimed.price | currency: 'EUR':2}}</td>
|
||||
<td number>{{::saleClaimed.discount}} %</td>
|
||||
<td number>{{saleClaimed.total | currency: 'EUR':2}}</td>
|
||||
<td shrink>
|
||||
<vn-icon-button
|
||||
vn-tooltip="Remove line"
|
||||
icon="delete"
|
||||
ng-click="model.remove($index)"
|
||||
ng-click="$ctrl.removeSales(saleClaimed)"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-data-viewer>
|
||||
<vn-button-bar>
|
||||
<vn-button
|
||||
label="Regularize"
|
||||
disabled="$ctrl.claim.claimStateFk == $ctrl.resolvedStateId"
|
||||
vn-http-click="$ctrl.regularize()">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</slot-table>
|
||||
</smart-table>
|
||||
<button-bar class="vn-pa-md">
|
||||
<vn-button
|
||||
label="Regularize"
|
||||
disabled="$ctrl.claim.claimStateFk == $ctrl.resolvedStateId"
|
||||
vn-http-click="$ctrl.regularize()">
|
||||
</vn-button>
|
||||
</button-bar>
|
||||
</vn-card>
|
||||
<vn-item-descriptor-popover
|
||||
vn-id="item-descriptor"
|
||||
|
@ -128,3 +149,28 @@
|
|||
message="Do you want to insert greuges?"
|
||||
on-accept="$ctrl.onUpdateGreugeAccept()">
|
||||
</vn-confirm>
|
||||
|
||||
<!-- Dialog of change destionation -->
|
||||
<vn-dialog
|
||||
vn-id="changeDestination"
|
||||
on-accept="$ctrl.onResponse()">
|
||||
<tpl-body>
|
||||
<section class="SMSDialog">
|
||||
<h5 class="vn-py-sm">{{$ctrl.$t('Change destination to all selected rows', {total: $ctrl.checked.length})}}</h5>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one id="claimDestinationFk"
|
||||
ng-model="$ctrl.newDestination"
|
||||
data="claimDestinations"
|
||||
fields="['id','description']"
|
||||
value-field="id"
|
||||
show-field="description"
|
||||
vn-focus>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</section>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Save</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -5,6 +5,7 @@ import './style.scss';
|
|||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.newDestination;
|
||||
this.filter = {
|
||||
include: [
|
||||
{relation: 'sale',
|
||||
|
@ -21,6 +22,81 @@ export default class Controller extends Section {
|
|||
};
|
||||
this.getResolvedState();
|
||||
this.maxResponsibility = 5;
|
||||
this.smartTableOptions = {
|
||||
activeButtons: {
|
||||
search: true
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'claimDestinationFk',
|
||||
autocomplete: {
|
||||
url: 'ClaimDestinations',
|
||||
showField: 'description',
|
||||
valueField: 'id'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'landed',
|
||||
searchable: false
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'itemFk':
|
||||
case 'ticketFk':
|
||||
case 'claimDestinationFk':
|
||||
case 'quantity':
|
||||
case 'price':
|
||||
case 'discount':
|
||||
case 'total':
|
||||
return {[param]: value};
|
||||
case 'concept':
|
||||
return {[param]: {like: `%${value}%`}};
|
||||
case 'landed':
|
||||
return {[param]: {between: this.dateRange(value)}};
|
||||
}
|
||||
}
|
||||
|
||||
dateRange(value) {
|
||||
const minHour = new Date(value);
|
||||
minHour.setHours(0, 0, 0, 0);
|
||||
const maxHour = new Date(value);
|
||||
maxHour.setHours(23, 59, 59, 59);
|
||||
|
||||
return [minHour, maxHour];
|
||||
}
|
||||
|
||||
get checked() {
|
||||
const salesClaimed = this.$.model.data || [];
|
||||
|
||||
const checkedSalesClaimed = [];
|
||||
for (let saleClaimed of salesClaimed) {
|
||||
if (saleClaimed.$checked)
|
||||
checkedSalesClaimed.push(saleClaimed);
|
||||
}
|
||||
|
||||
return checkedSalesClaimed;
|
||||
}
|
||||
|
||||
updateDestination(saleClaimed, claimDestinationFk) {
|
||||
const data = {rows: [saleClaimed], claimDestinationFk: claimDestinationFk};
|
||||
this.$http.post(`Claims/updateClaimDestination`, data).then(() => {
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
}).catch(e => {
|
||||
this.$.model.refresh();
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
removeSales(saleClaimed) {
|
||||
const params = {sales: [saleClaimed]};
|
||||
this.$http.post(`ClaimEnds/deleteClamedSales`, params).then(() => {
|
||||
this.$.model.refresh();
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
});
|
||||
}
|
||||
|
||||
getResolvedState() {
|
||||
|
@ -54,8 +130,8 @@ export default class Controller extends Section {
|
|||
calculateTotals() {
|
||||
this.claimedTotal = 0;
|
||||
this.salesClaimed.forEach(sale => {
|
||||
const price = sale.sale.quantity * sale.sale.price;
|
||||
const discount = (sale.sale.discount * (sale.sale.quantity * sale.sale.price)) / 100;
|
||||
const price = sale.quantity * sale.price;
|
||||
const discount = (sale.discount * (sale.quantity * sale.price)) / 100;
|
||||
this.claimedTotal += price - discount;
|
||||
});
|
||||
}
|
||||
|
@ -125,6 +201,24 @@ export default class Controller extends Section {
|
|||
onSave() {
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
}
|
||||
|
||||
onResponse() {
|
||||
const rowsToEdit = [];
|
||||
for (let row of this.checked)
|
||||
rowsToEdit.push({id: row.id});
|
||||
|
||||
const data = {
|
||||
rows: rowsToEdit,
|
||||
claimDestinationFk: this.newDestination
|
||||
};
|
||||
|
||||
const query = `Claims/updateClaimDestination`;
|
||||
this.$http.post(query, data)
|
||||
.then(() => {
|
||||
this.$.model.refresh();
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnClaimAction', {
|
||||
|
|
|
@ -43,9 +43,9 @@ describe('claim', () => {
|
|||
describe('calculateTotals()', () => {
|
||||
it('should calculate the total price of the items claimed', () => {
|
||||
controller.salesClaimed = [
|
||||
{sale: {quantity: 5, price: 2, discount: 0}},
|
||||
{sale: {quantity: 10, price: 2, discount: 0}},
|
||||
{sale: {quantity: 10, price: 2, discount: 0}}
|
||||
{quantity: 5, price: 2, discount: 0},
|
||||
{quantity: 10, price: 2, discount: 0},
|
||||
{quantity: 10, price: 2, discount: 0}
|
||||
];
|
||||
controller.calculateTotals();
|
||||
|
||||
|
@ -151,5 +151,17 @@ describe('claim', () => {
|
|||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('Greuge added');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onResponse()', () => {
|
||||
it('should perform a post query and show a success message', () => {
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
$httpBackend.expect('POST', `Claims/updateClaimDestination`).respond({});
|
||||
controller.onResponse();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,3 +8,6 @@ Do you want to insert greuges?: Desea insertar greuges?
|
|||
Insert greuges on client card: Insertar greuges en la ficha del cliente
|
||||
Greuge added: Greuge añadido
|
||||
ClaimGreugeDescription: Reclamación id {{claimId}}
|
||||
Change destination: Cambiar destino
|
||||
Change destination to all selected rows: Cambiar destino a {{total}} fila(s) seleccionada(s)
|
||||
Add observation to all selected clients: Añadir observación a {{total}} cliente(s) seleccionado(s)
|
||||
|
|
|
@ -6,7 +6,7 @@ vn-claim-action {
|
|||
align-content: center;
|
||||
|
||||
vn-tool-bar {
|
||||
flex: 1
|
||||
flex: none
|
||||
}
|
||||
|
||||
.vn-check {
|
||||
|
@ -39,4 +39,8 @@ vn-claim-action {
|
|||
max-height: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
margin-left: 370px;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue