Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 6106-fixSignView
gitea/salix/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Jorge Penadés 2024-02-13 09:36:07 +01:00
commit c8e13fa858
36 changed files with 588 additions and 215 deletions

View File

@ -49,7 +49,6 @@ module.exports = Self => {
Self.uploadFile = async(ctx, options) => { Self.uploadFile = async(ctx, options) => {
const models = Self.app.models; const models = Self.app.models;
const TempContainer = models.TempContainer; const TempContainer = models.TempContainer;
const DmsContainer = models.DmsContainer;
const fileOptions = {}; const fileOptions = {};
const args = ctx.args; const args = ctx.args;
@ -79,19 +78,21 @@ module.exports = Self => {
const addedDms = []; const addedDms = [];
for (const uploadedFile of files) { for (const uploadedFile of files) {
const newDms = await createDms(ctx, uploadedFile, myOptions);
const pathHash = DmsContainer.getHash(newDms.id);
const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name); const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name);
srcFile = path.join(file.client.root, file.container, file.name); srcFile = path.join(file.client.root, file.container, file.name);
const dmsContainer = await DmsContainer.container(pathHash); const data = {
const dstFile = path.join(dmsContainer.client.root, pathHash, newDms.file); workerFk: ctx.req.accessToken.userId,
dmsTypeFk: args.dmsTypeId,
await fs.move(srcFile, dstFile, { companyFk: args.companyId,
overwrite: true warehouseFk: args.warehouseId,
}); reference: args.reference,
description: args.description,
contentType: args.contentType,
hasFile: args.hasFile
};
const extension = await models.DmsContainer.getFileExtension(uploadedFile.name);
const newDms = await Self.createFromFile(data, extension, srcFile, myOptions);
addedDms.push(newDms); addedDms.push(newDms);
} }
@ -107,27 +108,4 @@ module.exports = Self => {
throw e; 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 Self.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);
}
}; };

View File

@ -1,4 +1,6 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
const fs = require('fs-extra');
const path = require('path');
module.exports = Self => { module.exports = Self => {
require('../methods/dms/downloadFile')(Self); require('../methods/dms/downloadFile')(Self);
@ -35,4 +37,32 @@ module.exports = Self => {
return [stream, dms.contentType, `filename="${dms.file}"`]; return [stream, dms.contentType, `filename="${dms.file}"`];
}; };
Self.getPath = async function(dms) {
const models = Self.app.models;
const pathHash = await models.DmsContainer.getHash(dms.id);
const dmsContainer = await models.DmsContainer.container(pathHash);
const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file);
return dstFile;
};
Self.createWithExtension = async function(data, extension, options) {
const newDms = await Self.create(data, options);
return newDms.updateAttribute('file', `${newDms.id}.${extension}`, options);
};
Self.createFromFile = async function(data, extension, srcFile, options) {
const dms = await Self.createWithExtension(data, extension, options);
const dstFile = await Self.getPath(dms);
await fs.move(srcFile, dstFile, {overwrite: true});
return dms;
};
Self.createFromStream = async function(data, extension, stream, options) {
const dms = await Self.createWithExtension(data, extension, options);
const dstFile = await Self.getPath(dms);
const writeStream = await fs.createWriteStream(dstFile);
await stream.pipe(writeStream);
return dms;
};
}; };

View File

@ -115,6 +115,7 @@ async function test() {
// runner.loadConfigFile('back/jasmine.json'); // runner.loadConfigFile('back/jasmine.json');
runner.loadConfig(config); runner.loadConfig(config);
process.env.SPEC_IS_RUNNING = true;
await runner.execute(); await runner.execute();
} }

View File

@ -66,9 +66,6 @@ UPDATE vn.supplier
SET isTrucker = 1 SET isTrucker = 1
WHERE id = 2; WHERE id = 2;
INSERT INTO vn.cmr (id, truckPlate, observations, senderInstruccions, paymentInstruccions, specialAgreements, created, companyFk, addressToFk, addressFromFk, supplierFk, packagesList, merchandiseDetail, state, landed, ead)
VALUES (2, NULL, NULL, NULL, 'Carriage paid', NULL, '2022-06-27 13:31:11.000', 442, 3, 2, 2, NULL, NULL, NULL, NULL, NULL);
-- XXX: tpv -- XXX: tpv
UPDATE `vn`.`claimRatio` SET `claimAmount` = '10' WHERE (`clientFk` = '1101'); UPDATE `vn`.`claimRatio` SET `claimAmount` = '10' WHERE (`clientFk` = '1101');

View File

@ -725,40 +725,40 @@ INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agen
(6, NULL, 57, util.VN_CURDATE(), 5, 7, 'sixth route', 1.7, 60, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 3), (6, NULL, 57, util.VN_CURDATE(), 5, 7, 'sixth route', 1.7, 60, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 3),
(7, NULL, 57, util.VN_CURDATE(), 6, 8, 'seventh route', 0, 70, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 5); (7, NULL, 57, util.VN_CURDATE(), 6, 8, 'seventh route', 0, 70, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 5);
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`) INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`, `cmrFk`)
VALUES VALUES
(1 , 3, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 121, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1), (1 , 3, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 121, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1),
(2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 1, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2), (2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 1, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 2),
(3 , 1, 7, 1, 6, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL), (3 , 1, 7, 1, 6, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL, 3),
(4 , 3, 2, 1, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 9, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL), (4 , 3, 2, 1, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 9, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL, NULL),
(5 , 3, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL), (5 , 3, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL, NULL),
(6 , 1, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL), (6 , 1, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, NULL),
(7 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (7 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(8 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Bat cave', 121, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (8 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Bat cave', 121, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(9 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (9 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(10, 1, 1, 5, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (10, 1, 1, 5, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(11, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (11, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(12, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (12, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(13, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (13, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(14, 1, 2, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, util.VN_CURDATE(), NULL), (14, 1, 2, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, util.VN_CURDATE(), NULL, NULL),
(15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), (17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
(18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +12 HOUR), NULL), (18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +12 HOUR), NULL, NULL),
(19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE(), NULL), (19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE(), NULL, NULL),
(20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL), (20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL, NULL),
(21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL), (21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL, NULL),
(22, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL), (22, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL, NULL),
(23, NULL, 8, 1, 7, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'address 21', 121, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL), (23, NULL, 8, 1, 7, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'address 21', 121, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL, NULL),
(24 ,NULL, 8, 1, 7, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL), (24 ,NULL, 8, 1, 7, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL, NULL),
(25 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (25 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(26 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (26 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), (31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
(32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL); (32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL);
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES VALUES
@ -2405,7 +2405,7 @@ INSERT INTO `vn`.`dmsType`(`id`, `name`, `readRoleFk`, `writeRoleFk`, `code`)
(14, 'Ticket', 1, 1, 'ticket'), (14, 'Ticket', 1, 1, 'ticket'),
(15, 'Presupuestos', NULL, NULL, 'budgets'), (15, 'Presupuestos', NULL, NULL, 'budgets'),
(16, 'Logistica', NULL, NULL, 'logistics'), (16, 'Logistica', NULL, NULL, 'logistics'),
(17, 'cmr', NULL, NULL, 'cmr'), (17, 'cmr', 1, 1, 'cmr'),
(18, 'dua', NULL, NULL, 'dua'), (18, 'dua', NULL, NULL, 'dua'),
(19, 'inmovilizado', NULL, NULL, 'fixedAssets'), (19, 'inmovilizado', NULL, NULL, 'fixedAssets'),
(20, 'Reclamación', 1, 1, 'claim'); (20, 'Reclamación', 1, 1, 'claim');
@ -3062,3 +3062,8 @@ INSERT INTO `vn`.`clientSms` (`id`, `clientFk`, `smsFk`, `ticketFk`)
(4, 1103, 4, 32), (4, 1103, 4, 32),
(13, 1101, 1, NULL), (13, 1101, 1, NULL),
(14, 1101, 4, 27); (14, 1101, 4, 27);
INSERT INTO `vn`.`cmr` (id,truckPlate,observations,senderInstruccions,paymentInstruccions,specialAgreements,companyFk,addressToFk,addressFromFk,supplierFk,packagesList,merchandiseDetail,state)
VALUES (1,'123456A','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',442,1,2,1,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'),
(2,'123456N','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',69,3,4,2,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'),
(3,'123456B','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',567,5,6,69,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet');

View File

@ -1,16 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `bi`.`nz`(vData DOUBLE)
RETURNS double
DETERMINISTIC
BEGIN
/**
* Devuelve 0, si el parámetro es NULL:
*/
DECLARE vResult DOUBLE;
SET vResult = IFNULL(vData,0);
RETURN vResult;
END$$
DELIMITER ;

View File

@ -130,13 +130,13 @@ BEGIN
-- Calculamos el porcentaje del recobro para añadirlo al precio de venta -- Calculamos el porcentaje del recobro para añadirlo al precio de venta
UPDATE bi.claims_ratio cr UPDATE bi.claims_ratio cr
JOIN ( JOIN (
SELECT Id_Cliente, nz(SUM(Importe)) AS Greuge SELECT Id_Cliente, IFNULL(SUM(Importe), 0) AS Greuge
FROM vn2008.Greuges FROM vn2008.Greuges
WHERE Fecha <= util.VN_CURDATE() WHERE Fecha <= util.VN_CURDATE()
GROUP BY Id_Cliente GROUP BY Id_Cliente
) g ON g.Id_Cliente = cr.Id_Cliente ) g ON g.Id_Cliente = cr.Id_Cliente
SET recobro = GREATEST(0,round(nz(Greuge) / SET recobro = GREATEST(0,round(IFNULL(Greuge, 0) /
(nz(Consumo) * vMonthToRefund / 12 ) ,3)); (IFNULL(Consumo, 0) * vMonthToRefund / 12 ) ,3));
-- Protección neonatos -- Protección neonatos
UPDATE bi.claims_ratio cr UPDATE bi.claims_ratio cr

View File

@ -1,14 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`nz`(vQuantity DOUBLE)
RETURNS double
DETERMINISTIC
BEGIN
DECLARE vResult DOUBLE;
SET vResult = IFNULL(vQuantity,0);
RETURN vResult;
END$$
DELIMITER ;

View File

@ -48,7 +48,7 @@ BEGIN
SELECT lc.companyFk, SELECT lc.companyFk,
c.id, c.id,
0, 0,
- (NZ(lc.credit) - NZ(lc.debit)) - (IFNULL(lc.credit, 0) - IFNULL(lc.debit, 0))
FROM tmp.ledgerComparative lc FROM tmp.ledgerComparative lc
JOIN client c ON c.accountingAccount = lc.account JOIN client c ON c.accountingAccount = lc.account
WHERE lc.`date` BETWEEN vDateFrom AND vDateTo WHERE lc.`date` BETWEEN vDateFrom AND vDateTo

View File

@ -60,7 +60,7 @@ BEGIN
SELECT lc.companyFk, SELECT lc.companyFk,
s.id, s.id,
0, 0,
- (NZ(lc.debit) - NZ(lc.credit)) - (IFNULL(lc.debit, 0) - IFNULL(lc.credit, 0))
FROM tmp.ledgerComparative lc FROM tmp.ledgerComparative lc
JOIN supplier s ON s.account = lc.account JOIN supplier s ON s.account = lc.account
WHERE lc.`date` BETWEEN vDateFrom AND vDateTo WHERE lc.`date` BETWEEN vDateFrom AND vDateTo

View File

@ -4,22 +4,22 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`expedition_beforeInse
FOR EACH ROW FOR EACH ROW
BEGIN BEGIN
DECLARE intcounter INT; DECLARE intcounter INT;
DECLARE vShipFk INT; DECLARE vShipFk INT;
SET NEW.editorFk = account.myUser_getId(); SET NEW.editorFk = account.myUser_getId();
IF NEW.freightItemFk IS NOT NULL THEN IF NEW.freightItemFk IS NOT NULL THEN
UPDATE ticket SET packages = nz(packages) + 1 WHERE id = NEW.ticketFk; UPDATE ticket SET packages = IFNULL(packages, 0) + 1 WHERE id = NEW.ticketFk;
SELECT IFNULL(MAX(counter),0) +1 INTO intcounter SELECT IFNULL(MAX(counter),0) +1 INTO intcounter
FROM expedition e FROM expedition e
INNER JOIN ticket t1 ON e.ticketFk = t1.id INNER JOIN ticket t1 ON e.ticketFk = t1.id
LEFT JOIN ticketState ts ON ts.ticketFk = t1.id LEFT JOIN ticketState ts ON ts.ticketFk = t1.id
INNER JOIN ticket t2 ON t2.addressFk = t1.addressFk AND DATE(t2.shipped) = DATE(t1.shipped) INNER JOIN ticket t2 ON t2.addressFk = t1.addressFk AND DATE(t2.shipped) = DATE(t1.shipped)
AND t1.warehouseFk = t2.warehouseFk AND t1.warehouseFk = t2.warehouseFk
WHERE t2.id = NEW.ticketFk AND ts.alertLevel < 3 AND t1.companyFk = t2.companyFk WHERE t2.id = NEW.ticketFk AND ts.alertLevel < 3 AND t1.companyFk = t2.companyFk
AND t1.agencyModeFk = t2.agencyModeFk; AND t1.agencyModeFk = t2.agencyModeFk;
SET NEW.`counter` = intcounter; SET NEW.`counter` = intcounter;
END IF; END IF;

View File

@ -1,14 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn2008`.`nz`(dblCANTIDAD DOUBLE)
RETURNS double
DETERMINISTIC
BEGIN
DECLARE dblRESULT DOUBLE;
SET dblRESULT = IFNULL(dblCANTIDAD,0);
RETURN dblRESULT;
END$$
DELIMITER ;

View File

@ -0,0 +1,9 @@
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn2008`.`credit`
AS SELECT `c`.`id` AS `id`,
`c`.`clientFk` AS `Id_Cliente`,
`c`.`workerFk` AS `Id_Trabajador`,
`c`.`amount` AS `amount`,
`c`.`created` AS `odbc_date`
FROM `vn`.`clientCredit` `c`

View File

@ -0,0 +1 @@
GRANT SELECT ON TABLE vn2008.credit TO financialBoss;

View File

@ -337,8 +337,9 @@
"You already have the mailAlias": "Ya tienes este alias de correo", "You already have the mailAlias": "Ya tienes este alias de correo",
"The alias cant be modified": "Este alias de correo no puede ser modificado", "The alias cant be modified": "Este alias de correo no puede ser modificado",
"No tickets to invoice": "No hay tickets para facturar", "No tickets to invoice": "No hay tickets para facturar",
"This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado",
"Name should be uppercase": "El nombre debe ir en mayúscula", "Name should be uppercase": "El nombre debe ir en mayúscula",
"Bank entity must be specified": "La entidad bancaria es obligatoria", "Bank entity must be specified": "La entidad bancaria es obligatoria",
"An email is necessary": "Es necesario un email", "An email is necessary": "Es necesario un email",
"You cannot update these fields": "No puedes actualizar estos campos", "You cannot update these fields": "No puedes actualizar estos campos",
"CountryFK cannot be empty": "El país no puede estar vacío" "CountryFK cannot be empty": "El país no puede estar vacío"

View File

@ -0,0 +1,89 @@
const {Email} = require('vn-print');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('cmrEmail', {
description: 'Sends the email with an cmr attached PDF',
accessType: 'WRITE',
accepts: [
{
arg: 'tickets',
type: ['number'],
required: true,
description: 'The ticket id',
}
],
http: {
path: '/cmrEmail',
verb: 'POST'
}
});
Self.cmrEmail = async function(ctx, tickets, options) {
const models = Self.app.models;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
for (const ticketId of tickets) {
const ticket = await models.Ticket.findOne({
where: {
id: ticketId
},
include: [{
relation: 'client',
fields: ['email']
}]
}, myOptions);
const recipient = ticket.client().email;
if (!recipient)
throw new UserError('There is no assigned email for this client');
const dms = await models.TicketDms.findOne({
where: {ticketFk: ticketId},
include: [{
relation: 'dms',
fields: ['id'],
scope: {
relation: 'dmsType',
scope: {
where: {code: 'cmr'}
}
}
}]
}, myOptions);
if (!dms) throw new UserError('Cmr file does not exist');
const response = await models.Dms.downloadFile(ctx, dms.id);
const email = new Email('cmr', {
ticketId,
lang: ctx.req.getLocale(),
recipient
});
await email.send({
overrideAttachments: true,
attachments: [{
filename: `${ticket.cmrFk}.pdf`,
content: response[0]
}]
});
}
if (tx) await tx.commit();
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,6 +1,4 @@
const JSZip = require('jszip'); const JSZip = require('jszip');
const axios = require('axios');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('downloadCmrsZip', { Self.remoteMethodCtx('downloadCmrsZip', {
@ -37,35 +35,20 @@ module.exports = Self => {
Self.downloadCmrsZip = async function(ctx, ids, options) { Self.downloadCmrsZip = async function(ctx, ids, options) {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {}; const myOptions = {};
const token = ctx.req.accessToken;
const zip = new JSZip(); const zip = new JSZip();
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const zipConfig = await models.ZipConfig.findOne(null, myOptions);
let totalSize = 0;
ids = ids.split(','); ids = ids.split(',');
try {
for (let id of ids) { for (const id of ids) {
if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); ctx.args = ctx.args || {};
const response = await axios.get( ctx.args.id = Number(id);
`${ctx.req.headers.referer}api/Routes/${id}/cmr?access_token=${token.id}`, { const [data] = await models.Route.cmr(ctx, myOptions);
...myOptions, zip.file(`${id}.pdf`, data, {binary: true});
responseType: 'arraybuffer',
});
if (response.headers['content-type'] !== 'application/pdf')
throw new UserError(`The response is not a PDF`);
zip.file(`${id}.pdf`, response.data, { binary: true });
}
const zipStream = zip.generateNodeStream({ streamFiles: true });
return [zipStream, 'application/zip', `filename="cmrs.zip"`];
} catch (e) {
throw e;
} }
const zipStream = zip.generateNodeStream({streamFiles: true});
return [zipStream, 'application/zip', `filename="cmrs.zip"`];
}; };
}; };

View File

@ -0,0 +1,25 @@
const models = require('vn-loopback/server/server').models;
describe('route downloadCmrsZip()', () => {
it('should create a zip file with the given cmr ids', async() => {
const tx = await models.Route.beginTransaction({});
const ctx = {
req: {
getLocale: () => {
return 'en';
},
accessToken: {userId: 9}
}
};
let cmrs = '1,2';
try {
const stream = await models.Route.downloadCmrsZip(ctx, cmrs);
expect(stream[0]).toBeDefined();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -0,0 +1,58 @@
{
"name": "Cmr",
"base": "VnModel",
"options": {
"mysql": {
"table": "cmr"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"truckPlate": {
"type": "number"
},
"observations": {
"type": "string"
},
"senderInstrucctions": {
"type": "string"
},
"paymentInstruccions": {
"type": "string"
},
"specialAgreements": {
"type": "string"
},
"created": {
"type": "date"
},
"companyFk": {
"type": "number"
},
"addressToFk": {
"type": "number"
},
"addressFromFk": {
"type": "number"
},
"supplierFk": {
"type": "number"
},
"packagesList": {
"type": "string"
},
"merchandiseDetail": {
"type": "string"
},
"landed": {
"type": "date"
},
"ead": {
"type": "date"
}
}
}

View File

@ -17,6 +17,7 @@ module.exports = Self => {
require('../methods/route/cmr')(Self); require('../methods/route/cmr')(Self);
require('../methods/route/getExternalCmrs')(Self); require('../methods/route/getExternalCmrs')(Self);
require('../methods/route/downloadCmrsZip')(Self); require('../methods/route/downloadCmrsZip')(Self);
require('../methods/route/cmrEmail')(Self);
require('../methods/route/getExpeditionSummary')(Self); require('../methods/route/getExpeditionSummary')(Self);
require('../methods/route/getByWorker')(Self); require('../methods/route/getByWorker')(Self);

View File

@ -0,0 +1,86 @@
const {Readable} = require('stream');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('saveCmr', {
description: 'Save cmr',
accessType: 'WRITE',
accepts: [
{
arg: 'tickets',
type: ['number'],
required: true,
description: 'The tickets'
}
],
http: {
path: `/saveCmr`,
verb: 'POST'
}
});
Self.saveCmr = async(ctx, tickets, options) => {
const models = Self.app.models;
const myOptions = {userId: ctx.req.accessToken.userId};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const dmsTypeCmr = await models.DmsType.findOne({
where: {code: 'cmr'},
fields: ['id']
}, myOptions);
for (const ticketId of tickets) {
const ticket = await models.Ticket.findById(ticketId, myOptions);
if (ticket.cmrFk) {
const hasDmsCmr = await models.TicketDms.findOne({
where: {ticketFk: ticketId},
include: {
relation: 'dms',
fields: ['dmsFk'],
scope: {
where: {dmsTypeFk: dmsTypeCmr.id}
}
}
}, myOptions);
if (hasDmsCmr?.dms())
throw new UserError('This ticket already has a cmr saved');
ctx.args.id = ticket.cmrFk;
const response = await models.Route.cmr(ctx, myOptions);
const pdfStream = Readable.from(Buffer.from(response[0]));
const data = {
workerFk: ctx.req.accessToken.userId,
dmsTypeFk: dmsTypeCmr.id,
companyFk: ticket.companyFk,
warehouseFk: ticket.warehouseFk,
reference: ticket.id,
contentType: 'application/pdf',
hasFile: true
};
const dms = await models.Dms.createFromStream(data, 'pdf', pdfStream, myOptions);
await models.TicketDms.create({
ticketFk: ticketId,
dmsFk: dms.id
}, myOptions);
}
}
if (tx) await tx.commit();
return;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -33,8 +33,9 @@ module.exports = Self => {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {userId: ctx.req.accessToken.userId}; const myOptions = {userId: ctx.req.accessToken.userId};
let tx; let tx;
let ticket;
let dms; let dms;
let gestDocCreated = false; let gestDocCreated;
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
@ -44,6 +45,11 @@ module.exports = Self => {
myOptions.transaction = tx; myOptions.transaction = tx;
} }
const dmsTypeTicket = await models.DmsType.findOne({
where: {code: 'ticket'},
fields: ['id']
}, myOptions);
async function setLocation(ticketId) { async function setLocation(ticketId) {
await models.Delivery.create({ await models.Delivery.create({
ticketFk: ticketId, ticketFk: ticketId,
@ -53,98 +59,105 @@ module.exports = Self => {
}, myOptions); }, myOptions);
} }
async function gestDocExists(ticketId) { async function hasSignDms(ticketId) {
const ticketDms = await models.TicketDms.findOne({ const ticketDms = await models.TicketDms.findOne({
where: {ticketFk: ticketId}, where: {ticketFk: ticketId},
fields: ['dmsFk'] include: [
{
relation: 'dms',
fields: ['id'],
scope: {
where: {dmsTypeFk: dmsTypeTicket.id}
}
}
]
}, myOptions); }, myOptions);
if (ticketDms?.dms()?.id) return true;
if (!ticketDms) return false;
const ticket = await models.Ticket.findById(ticketId, {fields: ['isSigned']}, myOptions);
if (ticket.isSigned == true)
return true;
else
await models.Dms.destroyAll({where: {reference: ticketId}}, myOptions);
return false;
} }
async function createGestDoc(id) { async function createGestDoc() {
const ticket = await models.Ticket.findById(id,
{
include: [
{
relation: 'warehouse',
scope: {
fields: ['id']
}
}, {
relation: 'client',
scope: {
fields: ['name']
}
}, {
relation: 'route',
scope: {
fields: ['id']
}
}
]
}, myOptions);
const dmsType = await models.DmsType.findOne({where: {code: 'Ticket'}, fields: ['id']}, myOptions);
const ctxUploadFile = Object.assign({}, ctx); const ctxUploadFile = Object.assign({}, ctx);
if (ticket.route() === null)
throw new UserError('Ticket without route');
ctxUploadFile.args = { ctxUploadFile.args = {
warehouseId: ticket.warehouseFk, warehouseId: ticket.warehouseFk,
companyId: ticket.companyFk, companyId: ticket.companyFk,
dmsTypeId: dmsType.id, dmsTypeId: dmsTypeTicket.id,
reference: '', reference: ticket.id,
description: `Firma del cliente - Ruta ${ticket.route().id}`, description: `Firma del cliente - Ruta ${ticket.route().id}`,
hasFile: false contentType: 'image/png',
hasFile: true
}; };
dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); dms = await models.Dms.uploadFile(ctxUploadFile, myOptions);
gestDocCreated = true; gestDocCreated = true;
} }
try { try {
let externalTickets = [];
for (const ticketId of tickets) { for (const ticketId of tickets) {
const ticketState = await models.TicketState.findOne( ticket = await models.Ticket.findById(ticketId, {
{where: {ticketFk: ticketId}, include: [{
fields: ['alertLevel'] relation: 'address',
}, myOptions); scope: {
include: {
relation: 'province',
scope: {
include: {
relation: 'country',
scope: {
fields: ['code']
}
}
}
}
}
}, {
relation: 'route',
scope: {
fields: ['id']
}
}]
}, myOptions);
const packedAlertLevel = await models.AlertLevel.findOne({where: {code: 'PACKED'}, const ticketState = await models.TicketState.findOne({
where: {ticketFk: ticketId},
fields: ['alertLevel']
}, myOptions);
const packedAlertLevel = await models.AlertLevel.findOne({
where: {code: 'PACKED'},
fields: ['id'] fields: ['id']
}, myOptions); }, myOptions);
if (!ticketState) if (!ticketState)
throw new UserError('Ticket does not exist'); throw new UserError('Ticket does not exist');
if (!ticket.route())
throw new UserError('Ticket without route');
if (ticketState.alertLevel < packedAlertLevel.id) if (ticketState.alertLevel < packedAlertLevel.id)
throw new UserError('This ticket cannot be signed because it has not been boxed'); throw new UserError('This ticket cannot be signed because it has not been boxed');
if (await gestDocExists(ticketId)) if (await ticket.isSigned)
throw new UserError('Ticket is already signed'); throw new UserError('Ticket is already signed');
if (location) await setLocation(ticketId); if (location) await setLocation(ticketId);
if (!gestDocCreated) await createGestDoc(ticketId); if (!await hasSignDms(ticketId) && !gestDocCreated)
await createGestDoc(ticketId);
await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions);
const ticket = await models.Ticket.findById(ticketId, null, myOptions);
await ticket.updateAttribute('isSigned', true, myOptions); await ticket.updateAttribute('isSigned', true, myOptions);
const deliveryState = await models.State.findOne({ const deliveryState = await models.State.findOne({
where: { where: {code: 'DELIVERED'}
code: 'DELIVERED'
}
}, myOptions); }, myOptions);
await models.Ticket.state(ctx, { await models.Ticket.state(ctx, {
ticketFk: ticketId, ticketFk: ticketId,
stateFk: deliveryState.id stateFk: deliveryState.id
}, myOptions); }, myOptions);
}
if (ticket?.address()?.province()?.country()?.code != 'ES') {
await models.Ticket.saveCmr(ctx, [ticketId], myOptions);
externalTickets.push(ticketId);
}
}
if (tx) await tx.commit(); if (tx) await tx.commit();
await models.Route.cmrEmail(ctx, externalTickets);
return; return;
} catch (e) { } catch (e) {
if (tx) await tx.rollback(); if (tx) await tx.rollback();

View File

@ -0,0 +1,41 @@
const models = require('vn-loopback/server/server').models;
describe('ticket saveCmr()', () => {
it(`should save cmr`, async() => {
const tx = await models.Ticket.beginTransaction({});
const ctx = {
req: {
getLocale: () => {
return 'en';
},
accessToken: {userId: 9}
},
args: {}
};
try {
const options = {transaction: tx};
const ticket = [2];
await models.Ticket.saveCmr(ctx, ticket, options);
const hasDmsCmr = await models.TicketDms.findOne({
where: {ticketFk: ticket[0]},
include: [{
relation: 'dms',
fields: ['id'],
scope: {
relation: 'dmsType',
scope: {
where: {code: 'cmr'}
}
}
}]
}, options);
expect(hasDmsCmr?.dms()?.id).toBeGreaterThanOrEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,14 +1,11 @@
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
describe('Ticket saveSign()', () => { describe('Ticket saveSign()', () => {
const FormData = require('form-data');
const data = new FormData();
let ctx = {req: { let ctx = {req: {
accessToken: {userId: 9}, getLocale: () => {
headers: { return 'en';
...data.getHeaders() },
} accessToken: {userId: 9}
}}; }};
it(`should throw error if the ticket's alert level is lower than 2`, async() => { it(`should throw error if the ticket's alert level is lower than 2`, async() => {
@ -17,9 +14,9 @@ describe('Ticket saveSign()', () => {
let error; let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
ctx.args = {tickets: [ticketWithOkState]}; const tickets = [ticketWithOkState];
await models.Ticket.saveSign(ctx, options); await models.Ticket.saveSign(ctx, tickets, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -41,6 +41,7 @@ module.exports = function(Self) {
require('../methods/ticket/collectionLabel')(Self); require('../methods/ticket/collectionLabel')(Self);
require('../methods/ticket/expeditionPalletLabel')(Self); require('../methods/ticket/expeditionPalletLabel')(Self);
require('../methods/ticket/saveSign')(Self); require('../methods/ticket/saveSign')(Self);
require('../methods/ticket/saveCmr')(Self);
require('../methods/ticket/invoiceTickets')(Self); require('../methods/ticket/invoiceTickets')(Self);
require('../methods/ticket/invoiceTicketsAndPdf')(Self); require('../methods/ticket/invoiceTicketsAndPdf')(Self);
require('../methods/ticket/docuwareDownload')(Self); require('../methods/ticket/docuwareDownload')(Self);

View File

@ -66,6 +66,9 @@
}, },
"weight": { "weight": {
"type": "number" "type": "number"
},
"cmrFk": {
"type": "number"
} }
}, },
"relations": { "relations": {
@ -139,6 +142,11 @@
"type": "belongsTo", "type": "belongsTo",
"model": "Zone", "model": "Zone",
"foreignKey": "zoneFk" "foreignKey": "zoneFk"
},
"cmrFk": {
"type": "belongsTo",
"model": "Cmr",
"foreignKey": "cmrFk"
} }
} }
} }

View File

@ -35,7 +35,8 @@ module.exports = {
logger.error(`[Print] => ${err.message}`); logger.error(`[Print] => ${err.message}`);
}); });
cluster.on('queue', () => logger.info('Printing task initialized by pool')); cluster.on('queue', () =>
process.env.SPEC_IS_RUNNING === 'false' && logger.info('Printing task initialized by pool'));
}); });
} }
}; };

View File

@ -0,0 +1,11 @@
const Stylesheet = require(`vn-print/core/stylesheet`);
const path = require('path');
const vnPrintPath = path.resolve('print');
module.exports = new Stylesheet([
`${vnPrintPath}/common/css/spacing.css`,
`${vnPrintPath}/common/css/misc.css`,
`${vnPrintPath}/common/css/layout.css`,
`${vnPrintPath}/common/css/email.css`])
.mergeStyles();

View File

@ -0,0 +1,6 @@
[
{
"filename": "cmr.pdf",
"component": "cmr"
}
]

View File

@ -0,0 +1,12 @@
<email-body v-bind="$props">
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dear')}},</p>
<p v-html="$t('description', [cmr.id, cmr.ticketFk])"></p>
<p v-html="$t('poll')"></p>
<p v-html="$t('help')"></p>
<p v-html="$t('conclusion')"></p>
</div>
</div>
</email-body>

View File

@ -0,0 +1,22 @@
const Component = require(`vn-print/core/component`);
const emailBody = new Component('email-body');
module.exports = {
name: 'cmr',
async serverPrefetch() {
this.cmr = await this.fetchCmr(this.ticketId);
},
methods: {
fetchCmr(ticketId) {
return this.findOneFromDef('cmr', [ticketId]);
},
},
components: {
'email-body': emailBody.build(),
},
props: {
ticketId: {
type: Number,
required: true
}
}
};

View File

@ -0,0 +1,9 @@
subject: Your CMR
title: Your CMR
dear: Dear Customer
description: The CMR <strong>{0}</strong> corresponding to order <strong>{1}</strong> is now available. <br/>
You can download it by clicking on the attachment in this email.
poll: If you wish, you can respond to our satisfaction survey to
help us provide better service. Your opinion is very important to us!
help: If you have any doubts, do not hesitate to ask, <strong>we are here to serve you!</strong>
conclusion: Thank you for your attention!

View File

@ -0,0 +1,9 @@
subject: Tu CMR
title: Tu CMR
dear: Estimado cliente
description: Ya está disponible el CMR <strong>{0}</strong> correspondiente al pedido <strong>{1}</strong>. <br/>
Puedes descargarla haciendo clic en el adjunto de este correo.
poll: Si lo deseas, puedes responder a nuestra encuesta de satisfacción para
ayudarnos a prestar un mejor servicio. ¡Tu opinión es muy importante para nosotros!
help: Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para atenderte!</strong>
conclusion: ¡Gracias por tu atención!

View File

@ -0,0 +1,9 @@
subject: Votre CMR
title: Votre CMR
dear: Cher client
description: Le CMR <strong>{0}</strong> correspondant à la commande <strong>{1}</strong> est maintenant disponible. <br/>
Vous pouvez le télécharger en cliquant sur la pièce jointe de cet e-mail.
poll: Si vous le souhaitez, vous pouvez répondre à notre enquête de satisfaction pour
nous aider à améliorer notre service. Votre avis est très important pour nous !
help: Si vous avez des doutes, n'hésitez pas à nous consulter, <strong>nous sommes là pour vous servir !</strong>
conclusion: Merci de votre attention !

View File

@ -0,0 +1,9 @@
subject: Seu CMR
title: Seu CMR
dear: Caro cliente
description: O CMR <strong>{0}</strong> correspondente ao pedido <strong>{1}</strong> já está disponível. <br/>
Você pode baixá-lo clicando no anexo deste e-mail.
poll: Se desejar, pode responder à nossa pesquisa de satisfação para
nos ajudar a oferecer um serviço melhor. Sua opinião é muito importante para nós!
help: Se tiver alguma dúvida, não hesite em nos consultar, <strong>estamos aqui para atendê-lo!</strong>
conclusion: Obrigado pela sua atenção!

View File

@ -0,0 +1,5 @@
SELECT t.id ticketFk,
c.id
FROM ticket t
JOIN cmr c ON c.id = t.cmrFk
WHERE t.id = ?