Merge branch 'dev' into 5056-gestion-vagones
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
39af68c3dc
|
@ -8,10 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## [2312.01] - 2023-04-06
|
## [2312.01] - 2023-04-06
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
-
|
- (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
-
|
- (Envíos -> Extra comunitarios) Se agrupan las entradas del mismo travel. Añadidos campos Referencia y Importe.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
-
|
-
|
||||||
|
|
|
@ -30,16 +30,23 @@ module.exports = Self => {
|
||||||
const recipient = to.replace('@', '');
|
const recipient = to.replace('@', '');
|
||||||
|
|
||||||
if (sender.name != recipient) {
|
if (sender.name != recipient) {
|
||||||
await models.Chat.create({
|
const chat = await models.Chat.create({
|
||||||
senderFk: sender.id,
|
senderFk: sender.id,
|
||||||
recipient: to,
|
recipient: to,
|
||||||
dated: Date.vnNew(),
|
dated: Date.vnNew(),
|
||||||
checkUserStatus: 0,
|
checkUserStatus: 0,
|
||||||
message: message,
|
message: message,
|
||||||
status: 0,
|
status: 'sending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
|
||||||
|
await Self.updateChat(chat, 'sent');
|
||||||
|
} catch (error) {
|
||||||
|
await Self.updateChat(chat, 'error', error);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.sendCheckingPresence = async(ctx, recipientId, message, options) => {
|
Self.sendCheckingPresence = async(ctx, recipientId, message) => {
|
||||||
if (!recipientId) return false;
|
if (!recipientId) return false;
|
||||||
|
|
||||||
const myOptions = {};
|
|
||||||
|
|
||||||
if (typeof options == 'object')
|
|
||||||
Object.assign(myOptions, options);
|
|
||||||
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const sender = await models.Account.findById(userId);
|
const sender = await models.Account.findById(userId, {fields: ['id']});
|
||||||
const recipient = await models.Account.findById(recipientId, null, myOptions);
|
const recipient = await models.Account.findById(recipientId, null);
|
||||||
|
|
||||||
// Prevent sending messages to yourself
|
// Prevent sending messages to yourself
|
||||||
if (recipientId == userId) return false;
|
if (recipientId == userId) return false;
|
||||||
|
@ -46,16 +41,23 @@ module.exports = Self => {
|
||||||
if (process.env.NODE_ENV == 'test')
|
if (process.env.NODE_ENV == 'test')
|
||||||
message = `[Test:Environment to user ${userId}] ` + message;
|
message = `[Test:Environment to user ${userId}] ` + message;
|
||||||
|
|
||||||
await models.Chat.create({
|
const chat = await models.Chat.create({
|
||||||
senderFk: sender.id,
|
senderFk: sender.id,
|
||||||
recipient: `@${recipient.name}`,
|
recipient: `@${recipient.name}`,
|
||||||
dated: Date.vnNew(),
|
dated: Date.vnNew(),
|
||||||
checkUserStatus: 1,
|
checkUserStatus: 1,
|
||||||
message: message,
|
message: message,
|
||||||
status: 0,
|
status: 'sending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Self.sendCheckingUserStatus(chat);
|
||||||
|
await Self.updateChat(chat, 'sent');
|
||||||
|
} catch (error) {
|
||||||
|
await Self.updateChat(chat, 'error', error);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,6 @@ module.exports = Self => {
|
||||||
Self.remoteMethodCtx('sendQueued', {
|
Self.remoteMethodCtx('sendQueued', {
|
||||||
description: 'Send a RocketChat message',
|
description: 'Send a RocketChat message',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [],
|
|
||||||
returns: {
|
returns: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
|
@ -16,14 +15,17 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.sendQueued = async() => {
|
Self.sendQueued = async() => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const maxAttempts = 3;
|
|
||||||
const sentStatus = 1;
|
|
||||||
const errorStatus = 2;
|
|
||||||
|
|
||||||
const chats = await models.Chat.find({
|
const chats = await models.Chat.find({
|
||||||
where: {
|
where: {
|
||||||
status: {neq: sentStatus},
|
status: {
|
||||||
attempts: {lt: maxAttempts}
|
nin: [
|
||||||
|
'sent',
|
||||||
|
'sending'
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
attempts: {lt: 3}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,16 +33,16 @@ module.exports = Self => {
|
||||||
if (chat.checkUserStatus) {
|
if (chat.checkUserStatus) {
|
||||||
try {
|
try {
|
||||||
await Self.sendCheckingUserStatus(chat);
|
await Self.sendCheckingUserStatus(chat);
|
||||||
await updateChat(chat, sentStatus);
|
await Self.updateChat(chat, 'sent');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await updateChat(chat, errorStatus, error);
|
await Self.updateChat(chat, 'error', error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
|
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
|
||||||
await updateChat(chat, sentStatus);
|
await Self.updateChat(chat, 'sent');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await updateChat(chat, errorStatus, error);
|
await Self.updateChat(chat, 'error', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,15 +130,17 @@ module.exports = Self => {
|
||||||
* @param {object} chat - The chat
|
* @param {object} chat - The chat
|
||||||
* @param {string} status - The new status
|
* @param {string} status - The new status
|
||||||
* @param {string} error - The error
|
* @param {string} error - The error
|
||||||
|
* @param {object} options - Query options
|
||||||
* @return {Promise} - The request promise
|
* @return {Promise} - The request promise
|
||||||
*/
|
*/
|
||||||
async function updateChat(chat, status, error) {
|
|
||||||
|
Self.updateChat = async(chat, status, error) => {
|
||||||
return chat.updateAttributes({
|
return chat.updateAttributes({
|
||||||
status: status,
|
status: status,
|
||||||
attempts: ++chat.attempts,
|
attempts: ++chat.attempts,
|
||||||
error: error
|
error: error
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current user status on Rocketchat
|
* Returns the current user status on Rocketchat
|
||||||
|
|
|
@ -10,7 +10,7 @@ describe('Chat sendCheckingPresence()', () => {
|
||||||
|
|
||||||
const chat = {
|
const chat = {
|
||||||
checkUserStatus: 1,
|
checkUserStatus: 1,
|
||||||
status: 0,
|
status: 'pending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ describe('Chat sendCheckingPresence()', () => {
|
||||||
|
|
||||||
const chat = {
|
const chat = {
|
||||||
checkUserStatus: 0,
|
checkUserStatus: 0,
|
||||||
status: 0,
|
status: 'pending',
|
||||||
attempts: 0
|
attempts: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('setSaleQuantity()', () => {
|
describe('setSaleQuantity()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should change quantity sale', async() => {
|
it('should change quantity sale', async() => {
|
||||||
const tx = await models.Ticket.beginTransaction({});
|
const tx = await models.Ticket.beginTransaction({});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
ALTER TABLE `vn`.`chat` ADD statusNew enum('pending','sent','error','sending') DEFAULT 'pending' NOT NULL;
|
||||||
|
|
||||||
|
UPDATE `vn`.`chat`
|
||||||
|
SET statusNew = 'pending'
|
||||||
|
WHERE status = 0;
|
||||||
|
|
||||||
|
UPDATE `vn`.`chat`
|
||||||
|
SET statusNew = 'sent'
|
||||||
|
WHERE status = 1;
|
||||||
|
|
||||||
|
UPDATE `vn`.`chat`
|
||||||
|
SET statusNew = 'error'
|
||||||
|
WHERE status = 2;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`chat` CHANGE status status__ tinyint(1) DEFAULT NULL NULL;
|
||||||
|
ALTER TABLE `vn`.`chat` CHANGE statusNew status enum('pending','sent','error','sending') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT 'pending' NOT NULL;
|
|
@ -0,0 +1,14 @@
|
||||||
|
ALTER TABLE `vn`.`itemType` ADD isFragile tinyint(1) NULL;
|
||||||
|
ALTER TABLE `vn`.`itemType` MODIFY COLUMN isFragile tinyint(1) DEFAULT 0 NOT NULL;
|
||||||
|
|
||||||
|
UPDATE `vn`.`itemType`
|
||||||
|
SET isFragile = 1
|
||||||
|
WHERE code IN ('ZKA', 'ZKE');
|
||||||
|
|
||||||
|
UPDATE `vn`.`itemType`
|
||||||
|
SET isFragile = 1
|
||||||
|
WHERE id IN (SELECT it.id
|
||||||
|
FROM itemCategory ic
|
||||||
|
JOIN itemType it ON it.categoryFk = ic.id
|
||||||
|
WHERE ic.code = 'plant');
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`ticket_getWarnings`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE PROCEDURE `vn`.`ticket_getWarnings`()
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Calcula las adventencias para un conjunto de tickets.
|
||||||
|
* Agrupados por ticket
|
||||||
|
*
|
||||||
|
* @table tmp.sale_getWarnings(ticketFk) Identificadores de los tickets a calcular
|
||||||
|
* @return tmp.ticket_warnings
|
||||||
|
*/
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.sale_warnings;
|
||||||
|
CREATE TEMPORARY TABLE tmp.sale_warnings (
|
||||||
|
ticketFk INT(11),
|
||||||
|
saleFk INT(11),
|
||||||
|
isFragile INTEGER(1) DEFAULT 0,
|
||||||
|
PRIMARY KEY (ticketFk, saleFk)
|
||||||
|
) ENGINE = MEMORY;
|
||||||
|
|
||||||
|
-- Frágil
|
||||||
|
INSERT INTO tmp.sale_warnings(ticketFk, saleFk, isFragile)
|
||||||
|
SELECT tt.ticketFk, s.id, TRUE
|
||||||
|
FROM tmp.sale_getWarnings tt
|
||||||
|
LEFT JOIN sale s ON s.ticketFk = tt.ticketFk
|
||||||
|
LEFT JOIN item i ON i.id = s.itemFk
|
||||||
|
LEFT JOIN itemType it ON it.id = i.typeFk
|
||||||
|
LEFT JOIN agencyMode am ON am.id = tt.agencyModeFk
|
||||||
|
LEFT JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
|
||||||
|
WHERE dm.code IN ('AGENCY')
|
||||||
|
AND it.isFragile;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_warnings;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticket_warnings
|
||||||
|
(PRIMARY KEY (ticketFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT
|
||||||
|
sw.ticketFk,
|
||||||
|
MAX(sw.isFragile) AS isFragile
|
||||||
|
FROM tmp.sale_warnings sw
|
||||||
|
GROUP BY sw.ticketFk;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE
|
||||||
|
tmp.sale_warnings;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -501,7 +501,8 @@ INSERT INTO `vn`.`observationType`(`id`,`description`, `code`)
|
||||||
(3, 'Delivery', 'delivery'),
|
(3, 'Delivery', 'delivery'),
|
||||||
(4, 'SalesPerson', 'salesPerson'),
|
(4, 'SalesPerson', 'salesPerson'),
|
||||||
(5, 'Administrative', 'administrative'),
|
(5, 'Administrative', 'administrative'),
|
||||||
(6, 'Weight', 'weight');
|
(6, 'Weight', 'weight'),
|
||||||
|
(7, 'InvoiceOut', 'invoiceOut');
|
||||||
|
|
||||||
INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`)
|
INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -738,7 +739,9 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
|
||||||
(9, 23, 5, 'care with the dog'),
|
(9, 23, 5, 'care with the dog'),
|
||||||
(10, 23, 4, 'Reclama ticket: 8'),
|
(10, 23, 4, 'Reclama ticket: 8'),
|
||||||
(11, 24, 4, 'Reclama ticket: 7'),
|
(11, 24, 4, 'Reclama ticket: 7'),
|
||||||
(12, 11, 3, 'Delivery after 10am');
|
(12, 11, 3, 'Delivery after 10am'),
|
||||||
|
(13, 1, 7, 'observation of ticket one'),
|
||||||
|
(14, 2, 7, 'observation of ticket two');
|
||||||
|
|
||||||
-- FIX for state hours on local, inter_afterInsert
|
-- FIX for state hours on local, inter_afterInsert
|
||||||
-- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND);
|
-- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND);
|
||||||
|
@ -838,14 +841,14 @@ INSERT INTO `vn`.`temperature`(`code`, `name`, `description`)
|
||||||
('warm', 'Warm', 'Warm'),
|
('warm', 'Warm', 'Warm'),
|
||||||
('cool', 'Cool', 'Cool');
|
('cool', 'Cool', 'Cool');
|
||||||
|
|
||||||
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`)
|
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`, `isFragile`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool'),
|
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool', 0),
|
||||||
(2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool'),
|
(2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool', 1),
|
||||||
(3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool'),
|
(3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool', 0),
|
||||||
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm'),
|
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm', 0),
|
||||||
(5, 'CON', 'Container', 3, NULL, 35, 1, 'warm'),
|
(5, 'CON', 'Container', 3, NULL, 35, 1, 'warm', 0),
|
||||||
(6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm');
|
(6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm', 1);
|
||||||
|
|
||||||
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2631,8 +2634,8 @@ INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackage
|
||||||
|
|
||||||
INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`)
|
INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`)
|
||||||
VALUES
|
VALUES
|
||||||
(1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 0),
|
(1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 'sent'),
|
||||||
(1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 0);
|
(1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 'pending');
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`)
|
INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`)
|
||||||
|
|
|
@ -524,7 +524,6 @@ export default {
|
||||||
},
|
},
|
||||||
itemLog: {
|
itemLog: {
|
||||||
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
|
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
|
||||||
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(4) td.after',
|
|
||||||
},
|
},
|
||||||
ticketSummary: {
|
ticketSummary: {
|
||||||
header: 'vn-ticket-summary > vn-card > h5',
|
header: 'vn-ticket-summary > vn-card > h5',
|
||||||
|
@ -1040,7 +1039,6 @@ export default {
|
||||||
boss: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bossFk"]',
|
boss: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bossFk"]',
|
||||||
role: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.roleFk"]',
|
role: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.roleFk"]',
|
||||||
iban: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.iban"]',
|
iban: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.iban"]',
|
||||||
switft: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bankEntityFk"]',
|
|
||||||
createButton: 'vn-worker-create vn-submit[label="Create"]',
|
createButton: 'vn-worker-create vn-submit[label="Create"]',
|
||||||
},
|
},
|
||||||
workerPda: {
|
workerPda: {
|
||||||
|
|
|
@ -27,7 +27,7 @@ describe('Worker time control path', () => {
|
||||||
date.setMonth(date.getMonth() + 1);
|
date.setMonth(date.getMonth() + 1);
|
||||||
let month = date.toLocaleString('default', {month: 'long'});
|
let month = date.toLocaleString('default', {month: 'long'});
|
||||||
|
|
||||||
await page.click(selectors.workerTimeControl.nextMonthButton);
|
await page.waitToClick(selectors.workerTimeControl.nextMonthButton);
|
||||||
let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
||||||
|
|
||||||
expect(result).toContain(month);
|
expect(result).toContain(month);
|
||||||
|
@ -36,7 +36,7 @@ describe('Worker time control path', () => {
|
||||||
date.setDate(1);
|
date.setDate(1);
|
||||||
month = date.toLocaleString('default', {month: 'long'});
|
month = date.toLocaleString('default', {month: 'long'});
|
||||||
|
|
||||||
await page.click(selectors.workerTimeControl.previousMonthButton);
|
await page.waitToClick(selectors.workerTimeControl.previousMonthButton);
|
||||||
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
||||||
|
|
||||||
expect(result).toContain(month);
|
expect(result).toContain(month);
|
||||||
|
@ -49,7 +49,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
await page.loginAndModule('salesBoss', 'worker');
|
await page.loginAndModule('salesBoss', 'worker');
|
||||||
await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`);
|
await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`);
|
||||||
await page.click(selectors.workerTimeControl.secondWeekDay);
|
await page.waitToClick(selectors.workerTimeControl.secondWeekDay);
|
||||||
|
|
||||||
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ describe('Worker create path', () => {
|
||||||
await page.write(selectors.workerCreate.street, 'S/ Doomstadt');
|
await page.write(selectors.workerCreate.street, 'S/ Doomstadt');
|
||||||
await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com');
|
await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com');
|
||||||
await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332');
|
await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332');
|
||||||
await page.autocompleteSearch(selectors.workerCreate.switft, 'BBKKESMMMMM');
|
|
||||||
|
|
||||||
// should check for autocompleted worker code and worker user name
|
// should check for autocompleted worker code and worker user name
|
||||||
const workerCode = await page
|
const workerCode = await page
|
||||||
|
|
|
@ -48,14 +48,14 @@ describe('Item log path', () => {
|
||||||
await page.accessToSection('item.card.log');
|
await page.accessToSection('item.card.log');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should confirm the log is showing 5 entries`, async() => {
|
it(`should confirm the log is showing 4 entries`, async() => {
|
||||||
await page.waitForSelector(selectors.itemLog.anyLineCreated);
|
await page.waitForSelector(selectors.itemLog.anyLineCreated);
|
||||||
const anyLineCreatedCount = await page.countElement(selectors.itemLog.anyLineCreated);
|
const anyLineCreatedCount = await page.countElement(selectors.itemLog.anyLineCreated);
|
||||||
|
|
||||||
expect(anyLineCreatedCount).toEqual(5);
|
expect(anyLineCreatedCount).toEqual(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should confirm the log is showing the intrastat for the created item`, async() => {
|
xit(`should confirm the log is showing the intrastat for the created item`, async() => {
|
||||||
const fifthLineCreatedProperty = await page
|
const fifthLineCreatedProperty = await page
|
||||||
.waitToGetProperty(selectors.itemLog.fifthLineCreatedProperty, 'innerText');
|
.waitToGetProperty(selectors.itemLog.fifthLineCreatedProperty, 'innerText');
|
||||||
|
|
||||||
|
|
|
@ -197,6 +197,7 @@ describe('Ticket Edit sale path', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check in the history that logs has been added', async() => {
|
it('should check in the history that logs has been added', async() => {
|
||||||
|
pending('https://redmine.verdnatura.es/issues/5455');
|
||||||
await page.reload({waitUntil: ['networkidle0', 'domcontentloaded']});
|
await page.reload({waitUntil: ['networkidle0', 'domcontentloaded']});
|
||||||
await page.waitToClick(selectors.ticketSales.firstSaleHistoryButton);
|
await page.waitToClick(selectors.ticketSales.firstSaleHistoryButton);
|
||||||
await page.waitForSelector(selectors.ticketSales.firstSaleHistory);
|
await page.waitForSelector(selectors.ticketSales.firstSaleHistory);
|
||||||
|
|
|
@ -54,7 +54,7 @@ describe('Ticket Future path', () => {
|
||||||
it('should search with the origin IPT', async() => {
|
it('should search with the origin IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('ipt=H');
|
expect(httpRequest).toContain('ipt=H');
|
||||||
|
@ -65,7 +65,7 @@ describe('Ticket Future path', () => {
|
||||||
|
|
||||||
await page.clearInput(selectors.ticketFuture.ipt);
|
await page.clearInput(selectors.ticketFuture.ipt);
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt=H');
|
expect(httpRequest).toContain('futureIpt=H');
|
||||||
|
@ -108,7 +108,7 @@ describe('Ticket Future path', () => {
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Destination', async() => {
|
it('should search in smart-table with an IPT Destination', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'H');
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt');
|
expect(httpRequest).toContain('futureIpt');
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
|
|
|
@ -54,7 +54,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search with the origin IPT', async() => {
|
it('should search with the origin IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H');
|
||||||
await page.waitToClick(selectors.ticketAdvance.submit);
|
await page.waitToClick(selectors.ticketAdvance.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt=H');
|
expect(httpRequest).toContain('futureIpt=H');
|
||||||
|
@ -66,7 +66,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search with the destination IPT', async() => {
|
it('should search with the destination IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H');
|
||||||
await page.waitToClick(selectors.ticketAdvance.submit);
|
await page.waitToClick(selectors.ticketAdvance.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('ipt=H');
|
expect(httpRequest).toContain('ipt=H');
|
||||||
|
@ -78,7 +78,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Origin', async() => {
|
it('should search in smart-table with an IPT Origin', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical');
|
await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'V');
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt');
|
expect(httpRequest).toContain('futureIpt');
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Destination', async() => {
|
it('should search in smart-table with an IPT Destination', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical');
|
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'V');
|
||||||
|
|
||||||
expect(httpRequest).toContain('ipt');
|
expect(httpRequest).toContain('ipt');
|
||||||
|
|
||||||
|
|
|
@ -89,11 +89,13 @@ describe('Travel basic data path', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to the travel logs', async() => {
|
it('should navigate to the travel logs', async() => {
|
||||||
|
pending('https://redmine.verdnatura.es/issues/5455');
|
||||||
await page.accessToSection('travel.card.log');
|
await page.accessToSection('travel.card.log');
|
||||||
await page.waitForState('travel.card.log');
|
await page.waitForState('travel.card.log');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check the 1st log contains details from the changes made', async() => {
|
it('should check the 1st log contains details from the changes made', async() => {
|
||||||
|
pending('https://redmine.verdnatura.es/issues/5455');
|
||||||
const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText');
|
const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText');
|
||||||
|
|
||||||
expect(result).toContain('new reference!');
|
expect(result).toContain('new reference!');
|
||||||
|
|
|
@ -26,13 +26,13 @@ module.exports = Self => {
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
const state = await models.ClaimState.findById(id, {
|
const state = await models.ClaimState.findById(id, {
|
||||||
include: {
|
include: {
|
||||||
relation: 'writeRole'
|
relation: 'writeRole'
|
||||||
}
|
}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
const roleWithGrants = state && state.writeRole().name;
|
const roleWithGrants = state && state.writeRole().name;
|
||||||
return await models.Account.hasRole(userId, roleWithGrants, myOptions);
|
return await models.Account.hasRole(userId, roleWithGrants, myOptions);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||||
const {mergeFilters, mergeWhere} = require('vn-loopback/util/filter');
|
const { mergeFilters, mergeWhere } = require('vn-loopback/util/filter');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('logs', {
|
Self.remoteMethodCtx('logs', {
|
||||||
|
@ -12,27 +12,27 @@ module.exports = Self => {
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
description: 'The claim id',
|
description: 'The claim id',
|
||||||
http: {source: 'path'}
|
http: { source: 'path' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'filter',
|
arg: 'filter',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
http: {source: 'query'}
|
http: { source: 'query' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'search',
|
arg: 'search',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
http: {source: 'query'}
|
http: { source: 'query' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'userFk',
|
arg: 'userFk',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
http: {source: 'query'}
|
http: { source: 'query' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'created',
|
arg: 'created',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
http: {source: 'query'}
|
http: { source: 'query' }
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -45,7 +45,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.logs = async(ctx, id, filter, options) => {
|
Self.logs = async (ctx, id, filter, options) => {
|
||||||
const conn = Self.dataSource.connector;
|
const conn = Self.dataSource.connector;
|
||||||
const args = ctx.args;
|
const args = ctx.args;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
@ -56,25 +56,25 @@ module.exports = Self => {
|
||||||
|
|
||||||
let where = buildFilter(args, (param, value) => {
|
let where = buildFilter(args, (param, value) => {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 'search':
|
case 'search':
|
||||||
return {
|
return {
|
||||||
or: [
|
or: [
|
||||||
{changedModel: {like: `%${value}%`}},
|
{ changedModel: { like: `%${value}%` } },
|
||||||
{oldInstance: {like: `%${value}%`}}
|
{ oldInstance: { like: `%${value}%` } }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
case 'userFk':
|
case 'userFk':
|
||||||
return {'cl.userFk': value};
|
return { 'cl.userFk': value };
|
||||||
case 'created':
|
case 'created':
|
||||||
value.setHours(0, 0, 0, 0);
|
value.setHours(0, 0, 0, 0);
|
||||||
to = new Date(value);
|
to = new Date(value);
|
||||||
to.setHours(23, 59, 59, 999);
|
to.setHours(23, 59, 59, 999);
|
||||||
|
|
||||||
return {creationDate: {between: [value, to]}};
|
return { creationDate: { between: [value, to] } };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
where = mergeWhere(where, {['cl.originFk']: id});
|
where = mergeWhere(where, { ['cl.originFk']: id });
|
||||||
filter = mergeFilters(args.filter, {where});
|
filter = mergeFilters(args.filter, { where });
|
||||||
|
|
||||||
const stmts = [];
|
const stmts = [];
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ module.exports = Self => {
|
||||||
const logs = [];
|
const logs = [];
|
||||||
for (const row of result) {
|
for (const row of result) {
|
||||||
const changes = [];
|
const changes = [];
|
||||||
const oldInstance = JSON.parse(row.oldInstance);
|
const oldInstance = JSON.parse(row.oldInstance) || {};
|
||||||
const newInstance = JSON.parse(row.newInstance);
|
const newInstance = JSON.parse(row.newInstance) || {};
|
||||||
const mergedProperties = [...Object.keys(oldInstance), ...Object.keys(newInstance)];
|
const mergedProperties = [...Object.keys(oldInstance), ...Object.keys(newInstance)];
|
||||||
const properties = new Set(mergedProperties);
|
const properties = new Set(mergedProperties);
|
||||||
for (const property of properties) {
|
for (const property of properties) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('claim regularizeClaim()', () => {
|
describe('claim regularizeClaim()', () => {
|
||||||
const userId = 18;
|
const userId = 18;
|
||||||
|
@ -39,6 +40,20 @@ describe('claim regularizeClaim()', () => {
|
||||||
return await models.ClaimEnd.create(claimEnds, options);
|
return await models.ClaimEnd.create(claimEnds, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
|
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
|
||||||
const tx = await models.Claim.beginTransaction({});
|
const tx = await models.Claim.beginTransaction({});
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,11 @@
|
||||||
"type": "hasMany",
|
"type": "hasMany",
|
||||||
"model": "ClaimDms",
|
"model": "ClaimDms",
|
||||||
"foreignKey": "claimFk"
|
"foreignKey": "claimFk"
|
||||||
|
},
|
||||||
|
"lines": {
|
||||||
|
"type": "hasMany",
|
||||||
|
"model": "ClaimBeginning",
|
||||||
|
"foreignKey": "claimFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ class Controller extends Section {
|
||||||
isClaimEditable() {
|
isClaimEditable() {
|
||||||
if (!this.claim) return;
|
if (!this.claim) return;
|
||||||
|
|
||||||
this.$http.get(`ClaimStates/${this.claim.id}/isEditable`).then(res => {
|
this.$http.get(`ClaimStates/${this.claim.claimStateFk}/isEditable`).then(res => {
|
||||||
this.isRewritable = res.data;
|
this.isRewritable = res.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ describe('claim', () => {
|
||||||
controller = $componentController('vnClaimDetail', {$element, $scope});
|
controller = $componentController('vnClaimDetail', {$element, $scope});
|
||||||
controller.claim = {
|
controller.claim = {
|
||||||
ticketFk: 1,
|
ticketFk: 1,
|
||||||
id: 2}
|
id: 2,
|
||||||
|
claimStateFk: 2}
|
||||||
;
|
;
|
||||||
controller.salesToClaim = [{saleFk: 1}, {saleFk: 2}];
|
controller.salesToClaim = [{saleFk: 1}, {saleFk: 2}];
|
||||||
controller.salesClaimed = [{id: 1, sale: {}}];
|
controller.salesClaimed = [{id: 1, sale: {}}];
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('Buy editLatestsBuys()', () => {
|
describe('Buy editLatestsBuys()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should change the value of a given column for the selected buys', async() => {
|
it('should change the value of a given column for the selected buys', async() => {
|
||||||
const tx = await models.Buy.beginTransaction({});
|
const tx = await models.Buy.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model": "EntryLog",
|
"model": "EntryLog",
|
||||||
"relation": "entry"
|
"relation": "entry",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
@ -70,4 +71,4 @@
|
||||||
"foreignKey": "packageFk"
|
"foreignKey": "packageFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"name": "Entry",
|
"name": "Entry",
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model":"EntryLog"
|
"model":"EntryLog",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('upsertFixedPrice()', () => {
|
describe('upsertFixedPrice()', () => {
|
||||||
const now = Date.vnNew();
|
const now = Date.vnNew();
|
||||||
|
@ -7,6 +8,17 @@ describe('upsertFixedPrice()', () => {
|
||||||
|
|
||||||
beforeAll(async() => {
|
beforeAll(async() => {
|
||||||
originalFixedPrice = await models.FixedPrice.findById(fixedPriceId);
|
originalFixedPrice = await models.FixedPrice.findById(fixedPriceId);
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should toggle the hasMinPrice boolean if there's a minPrice and update the rest of the data`, async() => {
|
it(`should toggle the hasMinPrice boolean if there's a minPrice and update the rest of the data`, async() => {
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('item clone()', () => {
|
describe('item clone()', () => {
|
||||||
let nextItemId;
|
let nextItemId;
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(async() => {
|
beforeEach(async() => {
|
||||||
let query = `SELECT i1.id + 1 as id FROM vn.item i1
|
let query = `SELECT i1.id + 1 as id FROM vn.item i1
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('item new()', () => {
|
describe('item new()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should create a new item, adding the name as a tag', async() => {
|
it('should create a new item, adding the name as a tag', async() => {
|
||||||
const tx = await models.Item.beginTransaction({});
|
const tx = await models.Item.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('regularize()', () => {
|
describe('regularize()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 18},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should create a new ticket and add a line', async() => {
|
it('should create a new ticket and add a line', async() => {
|
||||||
const tx = await models.Item.beginTransaction({});
|
const tx = await models.Item.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model": "ItemLog",
|
"model": "ItemLog",
|
||||||
"showField": "id"
|
"showField": "id",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
@ -220,4 +221,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,11 +295,26 @@ module.exports = Self => {
|
||||||
risk = t.debt + t.credit, totalProblems = totalProblems + 1
|
risk = t.debt + t.credit, totalProblems = totalProblems + 1
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getWarnings');
|
||||||
|
|
||||||
stmt = new ParameterizedSQL(`
|
stmt = new ParameterizedSQL(`
|
||||||
SELECT t.*, tp.*,
|
CREATE TEMPORARY TABLE tmp.sale_getWarnings
|
||||||
((tp.risk) + cc.riskTolerance < 0) AS hasHighRisk
|
(INDEX (ticketFk, agencyModeFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT f.id ticketFk, f.agencyModeFk
|
||||||
|
FROM tmp.filter f`);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmts.push('CALL ticket_getWarnings()');
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`
|
||||||
|
SELECT t.*,
|
||||||
|
tp.*,
|
||||||
|
((tp.risk) + cc.riskTolerance < 0) AS hasHighRisk,
|
||||||
|
tw.*
|
||||||
FROM tmp.tickets t
|
FROM tmp.tickets t
|
||||||
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id
|
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id
|
||||||
|
LEFT JOIN tmp.ticket_warnings tw ON tw.ticketFk = t.id
|
||||||
JOIN clientConfig cc`);
|
JOIN clientConfig cc`);
|
||||||
|
|
||||||
const hasProblems = args.problems;
|
const hasProblems = args.problems;
|
||||||
|
@ -387,6 +402,8 @@ module.exports = Self => {
|
||||||
tmp.filter,
|
tmp.filter,
|
||||||
tmp.ticket_problems,
|
tmp.ticket_problems,
|
||||||
tmp.sale_getProblems,
|
tmp.sale_getProblems,
|
||||||
|
tmp.sale_getWarnings,
|
||||||
|
tmp.ticket_warnings,
|
||||||
tmp.risk`);
|
tmp.risk`);
|
||||||
|
|
||||||
const sql = ParameterizedSQL.join(stmts, ';');
|
const sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
|
@ -12,4 +12,5 @@ Theoretical: Teórica
|
||||||
Practical: Práctica
|
Practical: Práctica
|
||||||
Preparation: Preparación
|
Preparation: Preparación
|
||||||
Auto-refresh: Auto-refresco
|
Auto-refresh: Auto-refresco
|
||||||
Toggle auto-refresh every 2 minutes: Conmuta el refresco automático cada 2 minutos
|
Toggle auto-refresh every 2 minutes: Conmuta el refresco automático cada 2 minutos
|
||||||
|
Is fragile: Es frágil
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
<vn-horizontal class="header">
|
<vn-horizontal class="header">
|
||||||
<vn-one translate>
|
<vn-one translate>
|
||||||
Tickets monitor
|
Tickets monitor
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-card>
|
<vn-card>
|
||||||
<smart-table
|
<smart-table
|
||||||
model="model"
|
model="model"
|
||||||
view-config-id="ticketsMonitor"
|
view-config-id="ticketsMonitor"
|
||||||
options="$ctrl.smartTableOptions"
|
options="$ctrl.smartTableOptions"
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||||
<slot-actions>
|
<slot-actions>
|
||||||
<vn-check
|
<vn-check
|
||||||
|
@ -68,6 +68,7 @@
|
||||||
<th field="stateFk">
|
<th field="stateFk">
|
||||||
<span translate>State</span>
|
<span translate>State</span>
|
||||||
</th>
|
</th>
|
||||||
|
<th field="isFragile"></th>
|
||||||
<th field="zoneFk">
|
<th field="zoneFk">
|
||||||
<span translate>Zone</span>
|
<span translate>Zone</span>
|
||||||
</th>
|
</th>
|
||||||
|
@ -80,7 +81,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="ticket in model.data track by ticket.id"
|
<tr ng-repeat="ticket in model.data track by ticket.id"
|
||||||
vn-anchor="{
|
vn-anchor="{
|
||||||
state: 'ticket.card.summary',
|
state: 'ticket.card.summary',
|
||||||
params: {id: ticket.id},
|
params: {id: ticket.id},
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
}">
|
}">
|
||||||
|
@ -169,12 +170,20 @@
|
||||||
class="link">
|
class="link">
|
||||||
{{ticket.refFk}}
|
{{ticket.refFk}}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
ng-show="!ticket.refFk"
|
ng-show="!ticket.refFk"
|
||||||
class="chip {{ticket.classColor}}">
|
class="chip {{ticket.classColor}}">
|
||||||
{{ticket.state}}
|
{{ticket.state}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td number>
|
||||||
|
<vn-icon
|
||||||
|
ng-show="ticket.isFragile"
|
||||||
|
translate-attr="{title: 'Is fragile'}"
|
||||||
|
class="bright"
|
||||||
|
icon="local_bar">
|
||||||
|
</vn-icon>
|
||||||
|
</td>
|
||||||
<td name="zone">
|
<td name="zone">
|
||||||
<span
|
<span
|
||||||
title="{{ticket.zoneName}}"
|
title="{{ticket.zoneName}}"
|
||||||
|
@ -191,8 +200,8 @@
|
||||||
<td actions>
|
<td actions>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
vn-anchor="{
|
vn-anchor="{
|
||||||
state: 'ticket.card.sale',
|
state: 'ticket.card.sale',
|
||||||
params: {id: ticket.id},
|
params: {id: ticket.id},
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
}"
|
}"
|
||||||
vn-tooltip="Go to lines"
|
vn-tooltip="Go to lines"
|
||||||
|
@ -213,7 +222,7 @@
|
||||||
<vn-ticket-descriptor-popover
|
<vn-ticket-descriptor-popover
|
||||||
vn-id="ticketDescriptor">
|
vn-id="ticketDescriptor">
|
||||||
</vn-ticket-descriptor-popover>
|
</vn-ticket-descriptor-popover>
|
||||||
<vn-worker-descriptor-popover
|
<vn-worker-descriptor-popover
|
||||||
vn-id="workerDescriptor">
|
vn-id="workerDescriptor">
|
||||||
</vn-worker-descriptor-popover>
|
</vn-worker-descriptor-popover>
|
||||||
<vn-client-descriptor-popover
|
<vn-client-descriptor-popover
|
||||||
|
@ -236,22 +245,22 @@
|
||||||
ng-click="contextmenu.filterBySelection()">
|
ng-click="contextmenu.filterBySelection()">
|
||||||
Filter by selection
|
Filter by selection
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item translate
|
<vn-item translate
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
ng-if="contextmenu.isFilterAllowed()"
|
||||||
ng-click="contextmenu.excludeSelection()">
|
ng-click="contextmenu.excludeSelection()">
|
||||||
Exclude selection
|
Exclude selection
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item translate
|
<vn-item translate
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
ng-if="contextmenu.isFilterAllowed()"
|
||||||
ng-click="contextmenu.removeFilter()">
|
ng-click="contextmenu.removeFilter()">
|
||||||
Remove filter
|
Remove filter
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item translate
|
<vn-item translate
|
||||||
ng-click="contextmenu.removeAllFilters()">
|
ng-click="contextmenu.removeAllFilters()">
|
||||||
Remove all filters
|
Remove all filters
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item translate
|
<vn-item translate
|
||||||
ng-if="contextmenu.isActionAllowed()"
|
ng-if="contextmenu.isActionAllowed()"
|
||||||
ng-click="contextmenu.copyValue()">
|
ng-click="contextmenu.copyValue()">
|
||||||
Copy value
|
Copy value
|
||||||
</vn-item>
|
</vn-item>
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('route clone()', () => {
|
describe('route clone()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const createdDate = Date.vnNew();
|
const createdDate = Date.vnNew();
|
||||||
it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => {
|
it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => {
|
||||||
const ids = [996, 997, 998, 999];
|
const ids = [996, 997, 998, 999];
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('route updateWorkCenter()', () => {
|
describe('route updateWorkCenter()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
const routeId = 1;
|
const routeId = 1;
|
||||||
|
|
||||||
it('should set the commission work center if the worker has workCenter', async() => {
|
it('should set the commission work center if the worker has workCenter', async() => {
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"name": "Route",
|
"name": "Route",
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model":"RouteLog"
|
"model":"RouteLog",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('sale canEdit()', () => {
|
describe('sale canEdit()', () => {
|
||||||
const employeeId = 1;
|
const employeeId = 1;
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('sale editTracked', () => {
|
describe('sale editTracked', () => {
|
||||||
it('should return true if the role is production regardless of the saleTrackings', async() => {
|
it('should return true if the role is production regardless of the saleTrackings', async() => {
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('sale deleteSales()', () => {
|
describe('sale deleteSales()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw an error if the ticket of the given sales is not editable', async() => {
|
it('should throw an error if the ticket of the given sales is not editable', async() => {
|
||||||
const tx = await models.Sale.beginTransaction({});
|
const tx = await models.Sale.beginTransaction({});
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('sale reserve()', () => {
|
describe('sale reserve()', () => {
|
||||||
const ctx = {
|
const ctx = {
|
||||||
|
@ -9,6 +10,20 @@ describe('sale reserve()', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw an error if the ticket can not be modified', async() => {
|
it('should throw an error if the ticket can not be modified', async() => {
|
||||||
const tx = await models.Sale.beginTransaction({});
|
const tx = await models.Sale.beginTransaction({});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('sale updateConcept()', () => {
|
describe('sale updateConcept()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: 9}}};
|
const ctx = {req: {accessToken: {userId: 9}}};
|
||||||
const saleId = 25;
|
const saleId = 25;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('sale updatePrice()', () => {
|
describe('sale updatePrice()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 18},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
req: {
|
req: {
|
||||||
accessToken: {userId: 18},
|
accessToken: {userId: 18},
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('sale updateQuantity()', () => {
|
describe('sale updateQuantity()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
req: {
|
req: {
|
||||||
accessToken: {userId: 9},
|
accessToken: {userId: 9},
|
||||||
|
|
|
@ -127,19 +127,6 @@ module.exports = Self => {
|
||||||
], myOptions);
|
], myOptions);
|
||||||
|
|
||||||
const ticket = await models.Ticket.findById(result[1][0].newTicketId, null, myOptions);
|
const ticket = await models.Ticket.findById(result[1][0].newTicketId, null, myOptions);
|
||||||
const cleanInstance = JSON.parse(JSON.stringify(ticket));
|
|
||||||
|
|
||||||
const logRecord = {
|
|
||||||
originFk: cleanInstance.id,
|
|
||||||
userFk: myUserId,
|
|
||||||
action: 'insert',
|
|
||||||
changedModel: 'Ticket',
|
|
||||||
changedModelId: cleanInstance.id,
|
|
||||||
oldInstance: {},
|
|
||||||
newInstance: cleanInstance
|
|
||||||
};
|
|
||||||
|
|
||||||
await models.TicketLog.create(logRecord, myOptions);
|
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('ticket addSale()', () => {
|
describe('ticket addSale()', () => {
|
||||||
const ticketId = 13;
|
const ticketId = 13;
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should create a new sale for the ticket with id 13', async() => {
|
it('should create a new sale for the ticket with id 13', async() => {
|
||||||
const tx = await models.Ticket.beginTransaction({});
|
const tx = await models.Ticket.beginTransaction({});
|
||||||
|
|
|
@ -10,11 +10,15 @@ describe('ticket merge()', () => {
|
||||||
workerFk: 1
|
workerFk: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
const activeCtx = {
|
beforeAll(async() => {
|
||||||
accessToken: {userId: 9},
|
const activeCtx = {
|
||||||
};
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
beforeEach(() => {
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
active: activeCtx
|
active: activeCtx
|
||||||
});
|
});
|
||||||
|
@ -35,16 +39,16 @@ describe('ticket merge()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
const chatNotificationBeforeMerge = await models.Chat.find();
|
const chatNotificationBeforeMerge = await models.Chat.find(null, options);
|
||||||
|
|
||||||
await models.Ticket.merge(ctx, [tickets], options);
|
await models.Ticket.merge(ctx, [tickets], options);
|
||||||
|
|
||||||
const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets.originId}}, options);
|
const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets.destinationId}}, options);
|
||||||
const deletedTicket = await models.Ticket.findOne({where: {id: tickets.originId}}, options);
|
const deletedTicket = await models.Ticket.findOne({where: {id: tickets.originId}}, options);
|
||||||
const salesTicketFuture = await models.Sale.find({where: {ticketFk: tickets.destinationId}}, options);
|
const salesTicketFuture = await models.Sale.find({where: {ticketFk: tickets.destinationId}}, options);
|
||||||
const chatNotificationAfterMerge = await models.Chat.find();
|
const chatNotificationAfterMerge = await models.Chat.find(null, options);
|
||||||
|
|
||||||
expect(createdTicketLog.length).toEqual(2);
|
expect(createdTicketLog.length).toEqual(1);
|
||||||
expect(deletedTicket.isDeleted).toEqual(true);
|
expect(deletedTicket.isDeleted).toEqual(true);
|
||||||
expect(salesTicketFuture.length).toEqual(2);
|
expect(salesTicketFuture.length).toEqual(2);
|
||||||
expect(chatNotificationBeforeMerge.length).toEqual(chatNotificationAfterMerge.length - 2);
|
expect(chatNotificationBeforeMerge.length).toEqual(chatNotificationAfterMerge.length - 2);
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('sale updateDiscount()', () => {
|
describe('sale updateDiscount()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
const originalSaleId = 8;
|
const originalSaleId = 8;
|
||||||
|
|
||||||
it('should throw an error if no sales were selected', async() => {
|
it('should throw an error if no sales were selected', async() => {
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
"log": {
|
"log": {
|
||||||
"model": "TicketLog",
|
"model": "TicketLog",
|
||||||
"relation": "ticket",
|
"relation": "ticket",
|
||||||
"showField": "concept"
|
"showField": "concept",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model":"TicketLog",
|
"model":"TicketLog",
|
||||||
"showField": "id"
|
"showField": "id",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
|
|
@ -130,6 +130,7 @@ module.exports = Self => {
|
||||||
SUM(b.stickers) AS stickers,
|
SUM(b.stickers) AS stickers,
|
||||||
s.id AS cargoSupplierFk,
|
s.id AS cargoSupplierFk,
|
||||||
s.nickname AS cargoSupplierNickname,
|
s.nickname AS cargoSupplierNickname,
|
||||||
|
s.name AS supplierName,
|
||||||
CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg,
|
CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg,
|
||||||
CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) as DECIMAL(10,0)) as volumeKg
|
CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) as DECIMAL(10,0)) as volumeKg
|
||||||
FROM travel t
|
FROM travel t
|
||||||
|
@ -167,6 +168,7 @@ module.exports = Self => {
|
||||||
SUM(b.stickers) AS stickers,
|
SUM(b.stickers) AS stickers,
|
||||||
e.evaNotes,
|
e.evaNotes,
|
||||||
e.notes,
|
e.notes,
|
||||||
|
e.invoiceAmount,
|
||||||
CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg,
|
CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg,
|
||||||
CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) AS DECIMAL(10,0)) as volumeKg
|
CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) AS DECIMAL(10,0)) as volumeKg
|
||||||
FROM tmp.travel tr
|
FROM tmp.travel tr
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model":"TravelLog",
|
"model":"TravelLog",
|
||||||
"showField": "ref"
|
"showField": "ref",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
url="Travels/extraCommunityFilter"
|
url="Travels/extraCommunityFilter"
|
||||||
user-params="::$ctrl.defaultFilter"
|
user-params="::$ctrl.defaultFilter"
|
||||||
data="travels"
|
data="travels"
|
||||||
order="shipped ASC, landed ASC, travelFk, loadPriority, agencyModeFk, evaNotes"
|
order="landed ASC, shipped ASC, travelFk, loadPriority, agencyModeFk, supplierName, evaNotes"
|
||||||
limit="20"
|
limit="20"
|
||||||
auto-load="true">
|
auto-load="true">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
|
@ -48,6 +48,9 @@
|
||||||
<th field="agencyModeFk">
|
<th field="agencyModeFk">
|
||||||
<span translate>Agency</span>
|
<span translate>Agency</span>
|
||||||
</th>
|
</th>
|
||||||
|
<th field="invoiceAmount">
|
||||||
|
<span translate>Amount</span>
|
||||||
|
</th>
|
||||||
<th field="ref">
|
<th field="ref">
|
||||||
<span translate>Reference</span>
|
<span translate>Reference</span>
|
||||||
</th>
|
</th>
|
||||||
|
@ -107,6 +110,7 @@
|
||||||
{{::travel.cargoSupplierNickname}}
|
{{::travel.cargoSupplierNickname}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td></td>
|
||||||
<td>{{::travel.agencyModeName}}</td>
|
<td>{{::travel.agencyModeName}}</td>
|
||||||
<td vn-click-stop>
|
<td vn-click-stop>
|
||||||
<vn-td-editable name="reference" expand>
|
<vn-td-editable name="reference" expand>
|
||||||
|
@ -157,22 +161,15 @@
|
||||||
{{::entry.supplierName}}
|
{{::entry.supplierName}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td number>{{::entry.invoiceAmount | currency: 'EUR': 2}}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td class="td-editable">{{::entry.ref}}</td>
|
<td class="td-editable">{{::entry.invoiceNumber}}</td>
|
||||||
<td number>{{::entry.stickers}}</td>
|
<td number>{{::entry.stickers}}</td>
|
||||||
<td number></td>
|
<td number></td>
|
||||||
<td number>{{::entry.loadedkg}}</td>
|
<td number>{{::entry.loadedkg}}</td>
|
||||||
<td number>{{::entry.volumeKg}}</td>
|
<td number>{{::entry.volumeKg}}</td>
|
||||||
<td>
|
<td></td>
|
||||||
<span ng-if="::entry.notes" vn-tooltip="{{::entry.notes}}">
|
<td></td>
|
||||||
{{::entry.notes}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span ng-if="::entry.evaNotes" vn-tooltip="{{::entry.evaNotes}}">
|
|
||||||
{{::entry.evaNotes}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
<div class="size50">
|
<div class="size50">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="header">{{$t('deliveryAddress')}}</div>
|
<div class="header">{{$t('deliveryAddress')}}</div>
|
||||||
<div class="body">
|
<div class="body" v-if="address">
|
||||||
<h3 class="uppercase">{{address.nickname}}</h3>
|
<h3 class="uppercase">{{address.nickname}}</h3>
|
||||||
<div>{{address.street}}</div>
|
<div>{{address.street}}</div>
|
||||||
<div>{{address.postalCode}}, {{address.city}} ({{address.province}})</div>
|
<div>{{address.postalCode}}, {{address.city}} ({{address.province}})</div>
|
||||||
|
@ -245,13 +245,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<report-footer
|
<report-footer id="pageFooter" v-bind:company-code="ticket.companyCode" v-bind:left-text="footerType"
|
||||||
id="pageFooter"
|
v-bind:center-text="client.socialName" v-bind="$props">
|
||||||
v-bind:company-code="ticket.companyCode"
|
|
||||||
v-bind:left-text="footerType"
|
|
||||||
v-bind:center-text="client.socialName"
|
|
||||||
v-bind="$props"
|
|
||||||
>
|
|
||||||
</report-footer>
|
</report-footer>
|
||||||
</template>
|
</template>
|
||||||
</report-body>
|
</report-body>
|
|
@ -240,13 +240,18 @@
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="columns vn-mt-xl" v-if="invoice.payMethodCode == 'wireTransfer'">
|
<div class="columns vn-mt-xl" v-if="invoice.payMethodCode == 'wireTransfer' || ticketObservations">
|
||||||
<div class="size50 pull-left no-page-break">
|
<div class="size50 pull-left no-page-break">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="header">{{$t('observations')}}</div>
|
<div class="header">{{$t('observations')}}</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div>{{$t('wireTransfer')}}</div>
|
<div v-if="invoice.payMethodCode == 'wireTransfer'">
|
||||||
<div>{{$t('accountNumber', [invoice.iban])}}</div>
|
<div>{{$t('wireTransfer')}}</div>
|
||||||
|
<div>{{$t('accountNumber', [invoice.iban])}}</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="ticketObservations">
|
||||||
|
{{ticketObservations}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,11 +21,15 @@ module.exports = {
|
||||||
|
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
|
|
||||||
|
this.ticketObservations = '';
|
||||||
for (let ticket of tickets) {
|
for (let ticket of tickets) {
|
||||||
ticket.sales = [];
|
ticket.sales = [];
|
||||||
|
|
||||||
map.set(ticket.id, ticket);
|
map.set(ticket.id, ticket);
|
||||||
|
|
||||||
|
if (ticket.description) this.ticketObservations += ticket.description + ' ';
|
||||||
}
|
}
|
||||||
|
this.ticketObservations = this.ticketObservations.trim();
|
||||||
|
|
||||||
for (let sale of sales) {
|
for (let sale of sales) {
|
||||||
const ticket = map.get(sale.ticketFk);
|
const ticket = map.get(sale.ticketFk);
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
SELECT
|
SELECT
|
||||||
t.id,
|
t.id,
|
||||||
t.shipped,
|
t.shipped,
|
||||||
t.nickname
|
t.nickname,
|
||||||
FROM invoiceOut io
|
tto.description
|
||||||
JOIN ticket t ON t.refFk = io.ref
|
FROM invoiceOut io
|
||||||
|
JOIN ticket t ON t.refFk = io.REF
|
||||||
|
LEFT JOIN observationType ot ON ot.code = 'invoiceOut'
|
||||||
|
LEFT JOIN ticketObservation tto ON tto.ticketFk = t.id
|
||||||
|
AND tto.observationTypeFk = ot.id
|
||||||
WHERE t.refFk = ?
|
WHERE t.refFk = ?
|
||||||
ORDER BY t.shipped
|
ORDER BY t.shipped
|
||||||
|
|
Loading…
Reference in New Issue