fixes #5633 Reutilizar accountShortToStandard en un nuevo componente #1541

Closed
alexandre wants to merge 20 commits from 5633-accountShortToStandard into dev
170 changed files with 1410 additions and 734 deletions
Showing only changes of commit 4678c67625 - Show all commits

View File

@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2342.01] - 2023-10-19 ## [2346.01] - 2023-11-16
### Added
### Changed
### Fixed
## [2342.01] - 2023-11-02
### Added ### Added
### Changed ### Changed

View File

@ -26,15 +26,14 @@ module.exports = Self => {
Self.sendCheckingPresence = async(ctx, recipientId, message) => { Self.sendCheckingPresence = async(ctx, recipientId, message) => {
if (!recipientId) return false; if (!recipientId) return false;
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.VnUser.findById(userId, {fields: ['id']}); const sender = await models.VnUser.findById(userId, {fields: ['id']});
const recipient = await models.VnUser.findById(recipientId, null); const recipient = await models.VnUser.findById(recipientId, null);
// Prevent sending messages to yourself // Prevent sending messages to yourself
if (recipientId == userId) return false; if (recipientId == userId) return false;
if (!recipient) if (!recipient)
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`); throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);

View File

@ -26,7 +26,7 @@ module.exports = Self => {
Self.getTickets = async(ctx, id, print, options) => { Self.getTickets = async(ctx, id, print, options) => {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const origin = ctx.req.headers.origin; const url = await Self.app.models.Url.getUrl();
const $t = ctx.req.__; const $t = ctx.req.__;
const myOptions = {}; const myOptions = {};
@ -36,7 +36,6 @@ module.exports = Self => {
myOptions.userId = userId; myOptions.userId = userId;
const promises = []; const promises = [];
const [tickets] = await Self.rawSql(`CALL vn.collection_getTickets(?)`, [id], myOptions); const [tickets] = await Self.rawSql(`CALL vn.collection_getTickets(?)`, [id], myOptions);
const sales = await Self.rawSql(` const sales = await Self.rawSql(`
SELECT s.ticketFk, SELECT s.ticketFk,
@ -86,24 +85,19 @@ module.exports = Self => {
if (tickets && tickets.length) { if (tickets && tickets.length) {
for (const ticket of tickets) { for (const ticket of tickets) {
const ticketId = ticket.ticketFk; const ticketId = ticket.ticketFk;
// SEND ROCKET
if (ticket.observaciones != '') { if (ticket.observaciones != '') {
for (observation of ticket.observaciones.split(' ')) { for (observation of ticket.observaciones.split(' ')) {
if (['#', '@'].includes(observation.charAt(0))) { if (['#', '@'].includes(observation.charAt(0))) {
promises.push(Self.app.models.Chat.send(ctx, observation, promises.push(Self.app.models.Chat.send(ctx, observation,
$t('The ticket is in preparation', { $t('The ticket is in preparation', {
ticketId: ticketId, ticketId: ticketId,
ticketUrl: `${origin}/#!/ticket/${ticketId}/summary`, ticketUrl: `${url}ticket/${ticketId}/summary`,
salesPersonId: ticket.salesPersonFk salesPersonId: ticket.salesPersonFk
}))); })));
} }
} }
} }
// SET COLLECTION
if (sales && sales.length) { if (sales && sales.length) {
// GET BARCODES
const barcodes = await Self.rawSql(` const barcodes = await Self.rawSql(`
SELECT s.id saleFk, b.code, c.id SELECT s.id saleFk, b.code, c.id
FROM vn.sale s FROM vn.sale s
@ -114,13 +108,10 @@ module.exports = Self => {
WHERE s.ticketFk = ? WHERE s.ticketFk = ?
AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`, AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`,
[ticketId], myOptions); [ticketId], myOptions);
// BINDINGS
ticket.sales = []; ticket.sales = [];
for (const sale of sales) { for (const sale of sales) {
if (sale.ticketFk === ticketId) { if (sale.ticketFk === ticketId) {
sale.Barcodes = []; sale.Barcodes = [];
if (barcodes && barcodes.length) { if (barcodes && barcodes.length) {
for (const barcode of barcodes) { for (const barcode of barcodes) {
if (barcode.saleFk === sale.saleFk) { if (barcode.saleFk === sale.saleFk) {
@ -131,7 +122,6 @@ module.exports = Self => {
} }
} }
} }
ticket.sales.push(sale); ticket.sales.push(sale);
} }
} }
@ -140,7 +130,6 @@ module.exports = Self => {
} }
} }
await Promise.all(promises); await Promise.all(promises);
return collection; return collection;
}; };
}; };

View File

@ -0,0 +1,30 @@
module.exports = Self => {
Self.remoteMethod('getUrl', {
description: 'Returns the colling app name',
accessType: 'READ',
accepts: [
{
arg: 'app',
type: 'string',
required: false
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/getUrl`,
verb: 'get'
}
});
Self.getUrl = async(appName = 'salix') => {
const {url} = await Self.app.models.Url.findOne({
where: {
appName,
enviroment: process.env.NODE_ENV || 'development'
}
});
return url;
};
};

View File

@ -7,17 +7,14 @@ module.exports = Self => {
Self.observe('before save', async function(ctx) { Self.observe('before save', async function(ctx) {
if (!ctx.isNewInstance) return; if (!ctx.isNewInstance) return;
let {message} = ctx.instance; let {message} = ctx.instance;
if (!message) return; if (!message) return;
const parts = message.match(/(?<=\[)[a-zA-Z0-9_\-+!@#$%^&*()={};':"\\|,.<>/?\s]*(?=])/g); const parts = message.match(/(?<=\[)[a-zA-Z0-9_\-+!@#$%^&*()={};':"\\|,.<>/?\s]*(?=])/g);
if (!parts) return; if (!parts) return;
const replacedParts = parts.map(part => { const replacedParts = parts.map(part => {
return part.replace(/[!$%^&*()={};':"\\,.<>/?]/g, ''); return part.replace(/[!$%^&*()={};':"\\,.<>/?]/g, '');
}); });
for (const [index, part] of parts.entries()) for (const [index, part] of parts.entries())
message = message.replace(part, replacedParts[index]); message = message.replace(part, replacedParts[index]);

View File

@ -1,3 +1,4 @@
module.exports = Self => { module.exports = Self => {
require('../methods/url/getByUser')(Self); require('../methods/url/getByUser')(Self);
require('../methods/url/getUrl')(Self);
}; };

View File

@ -1,7 +1,7 @@
const vnModel = require('vn-loopback/common/models/vn-model'); const vnModel = require('vn-loopback/common/models/vn-model');
const LoopBackContext = require('loopback-context');
const {Email} = require('vn-print'); const {Email} = require('vn-print');
const ForbiddenError = require('vn-loopback/util/forbiddenError'); const ForbiddenError = require('vn-loopback/util/forbiddenError');
const LoopBackContext = require('loopback-context');
module.exports = function(Self) { module.exports = function(Self) {
vnModel(Self); vnModel(Self);
@ -92,11 +92,7 @@ module.exports = function(Self) {
}; };
Self.on('resetPasswordRequest', async function(info) { Self.on('resetPasswordRequest', async function(info) {
const loopBackContext = LoopBackContext.getCurrentContext(); const url = await Self.app.models.Url.getUrl();
const httpCtx = {req: loopBackContext.active};
const httpRequest = httpCtx.req.http.req;
const headers = httpRequest.headers;
const origin = headers.origin;
const defaultHash = '/reset-password?access_token=$token$'; const defaultHash = '/reset-password?access_token=$token$';
const recoverHashes = { const recoverHashes = {
@ -112,7 +108,7 @@ module.exports = function(Self) {
const params = { const params = {
recipient: info.email, recipient: info.email,
lang: user.lang, lang: user.lang,
url: origin + '/#!' + recoverHash url: url.slice(0, -1) + recoverHash
}; };
const options = Object.assign({}, info.options); const options = Object.assign({}, info.options);

View File

@ -0,0 +1,133 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canAdvance`(vDateFuture DATE, vDateToAdvance DATE, vWarehouseFk INT)
BEGIN
/**
* Devuelve los tickets y la cantidad de lineas de venta que se pueden adelantar.
*
* @param vDateFuture Fecha de los tickets que se quieren adelantar.
* @param vDateToAdvance Fecha a cuando se quiere adelantar.
* @param vWarehouseFk Almacén
*/
DECLARE vDateInventory DATE;
SELECT inventoried INTO vDateInventory FROM config;
DROP TEMPORARY TABLE IF EXISTS tmp.stock;
CREATE TEMPORARY TABLE tmp.stock
(itemFk INT PRIMARY KEY,
amount INT)
ENGINE = MEMORY;
INSERT INTO tmp.stock(itemFk, amount)
SELECT itemFk, SUM(quantity) amount FROM
(
SELECT itemFk, quantity
FROM itemTicketOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryIn
WHERE landed >= vDateInventory
AND landed < vDateFuture
AND isVirtualStock = FALSE
AND warehouseInFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseOutFk = vWarehouseFk
) t
GROUP BY itemFk HAVING amount != 0;
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
(INDEX (id))
SELECT
origin.ticketFk futureId,
dest.ticketFk id,
dest.state,
origin.futureState,
origin.futureIpt,
dest.ipt,
origin.workerFk,
origin.futureLiters,
origin.futureLines,
dest.shipped,
origin.shipped futureShipped,
dest.totalWithVat,
origin.totalWithVat futureTotalWithVat,
dest.agency,
origin.futureAgency,
dest.lines,
dest.liters,
origin.futureLines - origin.hasStock AS notMovableLines,
(origin.futureLines = origin.hasStock) AS isFullMovable,
origin.futureZoneFk,
origin.futureZoneName,
origin.classColor futureClassColor,
dest.classColor
FROM (
SELECT
s.ticketFk,
c.salesPersonFk workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
t.addressFk,
am.name futureAgency,
count(s.id) futureLines,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters,
SUM((s.quantity <= IFNULL(st.amount,0))) hasStock,
z.id futureZoneFk,
z.name futureZoneName,
st.classColor
FROM ticket t
JOIN client c ON c.id = t.clientFk
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
JOIN zone z ON t.zoneFk = z.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN tmp.stock st ON st.itemFk = i.id
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
) origin
JOIN (
SELECT
t.id ticketFk,
t.addressFk,
st.name state,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt,
t.shipped,
t.totalWithVat,
am.name agency,
CAST(SUM(litros) AS DECIMAL(10,0)) liters,
CAST(COUNT(*) AS DECIMAL(10,0)) `lines`,
st.classColor
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
WHERE t.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance)
AND t.warehouseFk = vWarehouseFk
AND st.order <= 5
GROUP BY t.id
) dest ON dest.addressFk = origin.addressFk
WHERE origin.hasStock != 0;
DROP TEMPORARY TABLE tmp.stock;
END$$
DELIMITER ;

View File

@ -0,0 +1 @@
DROP PROCEDURE IF EXISTS `vn`.`workerCreate`;

View File

View File

@ -0,0 +1,12 @@
UPDATE `salix`.`ACL`
SET `property` = 'state',
`model` = 'Ticket'
WHERE `property` = 'changeState';
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'productionboss'@;
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'productionAssi'@;
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'hr'@;
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'salesPerson'@;
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'deliveryPerson'@;
REVOKE INSERT, UPDATE, DELETE ON `vn`.`ticketTracking` FROM 'employee'@;
REVOKE EXECUTE ON `vn`.`ticket_setState` FROM 'employee'@;

View File

@ -0,0 +1,13 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`expeditionState_BeforeInsert`
BEFORE INSERT ON `expeditionState`
FOR EACH ROW
BEGIN
SET NEW.userFk = IFNULL(NEW.userFk, account.myUser_getId());
END$$
DELIMITER ;

View File

@ -0,0 +1,55 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setState`(
vSelf INT,
vStateCode VARCHAR(255) COLLATE utf8_general_ci
)
BEGIN
/**
* Modifica el estado de un ticket si se cumplen las condiciones necesarias.
*
* @param vSelf el id del ticket
* @param vStateCode estado a modificar del ticket
*/
DECLARE vticketAlertLevel INT;
DECLARE vTicketStateCode VARCHAR(255);
DECLARE vCanChangeState BOOL;
DECLARE vPackedAlertLevel INT;
DECLARE vZoneFk INT;
SELECT s.alertLevel, s.`code`, t.zoneFk
INTO vticketAlertLevel, vTicketStateCode, vZoneFk
FROM state s
JOIN ticketTracking tt ON tt.stateFk = s.id
JOIN ticket t ON t.id = tt.ticketFk
WHERE tt.ticketFk = vSelf
ORDER BY tt.created DESC
LIMIT 1;
SELECT id INTO vPackedAlertLevel FROM alertLevel WHERE code = 'PACKED';
IF vStateCode = 'OK' AND vZoneFk IS NULL THEN
CALL util.throw('ASSIGN_ZONE_FIRST');
END IF;
SET vCanChangeState = (
vStateCode <> 'ON_CHECKING' OR
vticketAlertLevel < vPackedAlertLevel
)AND NOT (
vTicketStateCode IN ('CHECKED', 'CHECKING')
AND vStateCode IN ('PREPARED', 'ON_PREPARATION')
);
IF vCanChangeState THEN
INSERT INTO ticketTracking (stateFk, ticketFk, workerFk)
SELECT id, vSelf, account.myUser_getId()
FROM state
WHERE `code` = vStateCode COLLATE utf8_unicode_ci;
IF vStateCode = 'PACKED' THEN
CALL ticket_doCmr(vSelf);
END IF;
ELSE
CALL util.throw('INCORRECT_TICKET_STATE');
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,6 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('CplusInvoiceType477', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative');

View File

@ -604,7 +604,7 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF
INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`)
VALUES VALUES
(1, 'T', 1014.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(4, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (4, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
@ -2977,3 +2977,9 @@ INSERT INTO vn.XDiario (id, ASIEN, FECHA, SUBCTA, CONTRA, CONCEPTO, EURODEBE, EU
INSERT INTO `vn`.`mistakeType` (`id`, `description`) INSERT INTO `vn`.`mistakeType` (`id`, `description`)
VALUES VALUES
(1, 'Incorrect quantity'); (1, 'Incorrect quantity');
INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`)
VALUES
(1, 'Error in VAT calculation'),
(2, 'Error in sales details'),
(3, 'Error in customer data');

View File

@ -53,7 +53,8 @@ describe('ticket ticketCalculateClon()', () => {
expect(result[orderIndex][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures); expect(result[orderIndex][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures);
}); });
it('should add the ticket to the order containing the original ticket and generate landed value if it was null', async() => { it('should add the ticket to the order containing the original ' +
'ticket and generate landed value if it was null', async() => {
let stmts = []; let stmts = [];
let stmt; let stmt;

View File

@ -409,11 +409,11 @@ export default {
inactiveIcon: 'vn-item-descriptor vn-icon[icon="icon-unavailable"]' inactiveIcon: 'vn-item-descriptor vn-icon[icon="icon-unavailable"]'
}, },
itemRequest: { itemRequest: {
firstRequestItemID: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(7)', firstRequestItemID: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(8)',
firstRequestQuantity: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(8)', firstRequestQuantity: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(9)',
firstRequestConcept: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(9)', firstRequestConcept: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(10)',
firstRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(10)', firstRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(11)',
secondRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(10)', secondRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(11)',
secondRequestDecline: 'vn-item-request vn-tr:nth-child(2) vn-icon-button[icon="thumb_down"]', secondRequestDecline: 'vn-item-request vn-tr:nth-child(2) vn-icon-button[icon="thumb_down"]',
declineReason: 'vn-textarea[ng-model="$ctrl.denyObservation"]' declineReason: 'vn-textarea[ng-model="$ctrl.denyObservation"]'
}, },

View File

@ -212,7 +212,7 @@ describe('Ticket Edit sale path', () => {
it('should log in as salesAssistant and navigate to ticket sales', async() => { it('should log in as salesAssistant and navigate to ticket sales', async() => {
await page.loginAndModule('salesAssistant', 'ticket'); await page.loginAndModule('salesAssistant', 'ticket');
await page.accessToSearchResult('17'); await page.accessToSearchResult('15');
await page.accessToSection('ticket.card.sale'); await page.accessToSection('ticket.card.sale');
}); });
@ -316,7 +316,7 @@ describe('Ticket Edit sale path', () => {
}); });
it('should confirm the transfered quantity is the correct one', async() => { it('should confirm the transfered quantity is the correct one', async() => {
const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleQuantityCell, 'innerText'); const result = await page.waitToGetProperty(selectors.ticketSales.firstSaleQuantityCell, 'innerText');
expect(result).toContain('20'); expect(result).toContain('20');
}); });
@ -370,7 +370,7 @@ describe('Ticket Edit sale path', () => {
await page.waitToClick(selectors.ticketSales.moveToNewTicketButton); await page.waitToClick(selectors.ticketSales.moveToNewTicketButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain(`You can't create a ticket for a inactive client`); expect(message.text).toContain(`You can't create a ticket for an inactive client`);
await page.closePopup(); await page.closePopup();
}); });

View File

@ -1,4 +1,4 @@
FROM debian:stretch-slim FROM debian:bookworm-slim
EXPOSE 80 EXPOSE 80
ENV TZ Europe/Madrid ENV TZ Europe/Madrid

View File

@ -13,6 +13,6 @@
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "$everyone",
"permission": "ALLOW" "permission": "ALLOW"
} }
] ]
} }

View File

@ -23,7 +23,7 @@
"Agency cannot be blank": "Agency cannot be blank", "Agency cannot be blank": "Agency cannot be blank",
"The IBAN does not have the correct format": "The IBAN does not have the correct format", "The IBAN does not have the correct format": "The IBAN does not have the correct format",
"You can't make changes on the basic data of an confirmed order or with rows": "You can't make changes on the basic data of an confirmed order or with rows", "You can't make changes on the basic data of an confirmed order or with rows": "You can't make changes on the basic data of an confirmed order or with rows",
"You can't create a ticket for a inactive client": "You can't create a ticket for a inactive client", "You can't create a ticket for an inactive client": "You can't create a ticket for an inactive client",
"Worker cannot be blank": "Worker cannot be blank", "Worker cannot be blank": "Worker cannot be blank",
"You must delete the claim id %d first": "You must delete the claim id %d first", "You must delete the claim id %d first": "You must delete the claim id %d first",
"You don't have enough privileges": "You don't have enough privileges", "You don't have enough privileges": "You don't have enough privileges",
@ -188,7 +188,14 @@
"The ticket doesn't exist.": "The ticket doesn't exist.", "The ticket doesn't exist.": "The ticket doesn't exist.",
"The sales do not exists": "The sales do not exists", "The sales do not exists": "The sales do not exists",
"Ticket without Route": "Ticket without route", "Ticket without Route": "Ticket without route",
"Select a different client": "Select a different client",
"Fill all the fields": "Fill all the fields",
"Error while generating PDF": "Error while generating PDF",
"Can't invoice to future": "Can't invoice to future",
"This ticket is already invoiced": "This ticket is already invoiced",
"Negative basis of tickets: 23": "Negative basis of tickets: 23",
"Booking completed": "Booking complete", "Booking completed": "Booking complete",
"The ticket is in preparation": "The ticket [{{ticketId}}]({{{ticketUrl}}}) of the sales person {{salesPersonId}} is in preparation", "The ticket is in preparation": "The ticket [{{ticketId}}]({{{ticketUrl}}}) of the sales person {{salesPersonId}} is in preparation",
"You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets" "You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets"
} }

View File

@ -5,10 +5,10 @@
"The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado", "The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado",
"Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado", "Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado",
"Can't be blank": "No puede estar en blanco", "Can't be blank": "No puede estar en blanco",
"Invalid TIN": "NIF/CIF invalido", "Invalid TIN": "NIF/CIF inválido",
"TIN must be unique": "El NIF/CIF debe ser único", "TIN must be unique": "El NIF/CIF debe ser único",
"A client with that Web User name already exists": "Ya existe un cliente con ese Usuario Web", "A client with that Web User name already exists": "Ya existe un cliente con ese Usuario Web",
"Is invalid": "Is invalid", "Is invalid": "Es inválido",
"Quantity cannot be zero": "La cantidad no puede ser cero", "Quantity cannot be zero": "La cantidad no puede ser cero",
"Enter an integer different to zero": "Introduce un entero distinto de cero", "Enter an integer different to zero": "Introduce un entero distinto de cero",
"Package cannot be blank": "El embalaje no puede estar en blanco", "Package cannot be blank": "El embalaje no puede estar en blanco",
@ -55,17 +55,17 @@
"You must delete the claim id %d first": "Antes debes borrar la reclamación %d", "You must delete the claim id %d first": "Antes debes borrar la reclamación %d",
"You don't have enough privileges": "No tienes suficientes permisos", "You don't have enough privileges": "No tienes suficientes permisos",
"Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF", "Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF",
"You can't make changes on the basic data of an confirmed order or with rows": "No puedes cambiar los datos basicos de una orden con artículos", "You can't make changes on the basic data of an confirmed order or with rows": "No puedes cambiar los datos básicos de una orden con artículos",
"INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no esta permitido el uso de la letra ñ", "INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no está permitido el uso de la letra ñ",
"You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado", "You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado",
"You can't create a ticket for a inactive client": "No puedes crear un ticket para un cliente inactivo", "You can't create a ticket for an inactive client": "No puedes crear un ticket para un cliente inactivo",
"Tag value cannot be blank": "El valor del tag no puede quedar en blanco", "Tag value cannot be blank": "El valor del tag no puede quedar en blanco",
"ORDER_EMPTY": "Cesta vacía", "ORDER_EMPTY": "Cesta vacía",
"You don't have enough privileges to do that": "No tienes permisos para cambiar esto", "You don't have enough privileges to do that": "No tienes permisos para cambiar esto",
"NO SE PUEDE DESACTIVAR EL CONSIGNAT": "NO SE PUEDE DESACTIVAR EL CONSIGNAT", "NO SE PUEDE DESACTIVAR EL CONSIGNAT": "NO SE PUEDE DESACTIVAR EL CONSIGNAT",
"Error. El NIF/CIF está repetido": "Error. El NIF/CIF está repetido", "Error. El NIF/CIF está repetido": "Error. El NIF/CIF está repetido",
"Street cannot be empty": "Dirección no puede estar en blanco", "Street cannot be empty": "Dirección no puede estar en blanco",
"City cannot be empty": "Cuidad no puede estar en blanco", "City cannot be empty": "Ciudad no puede estar en blanco",
"Code cannot be blank": "Código no puede estar en blanco", "Code cannot be blank": "Código no puede estar en blanco",
"You cannot remove this department": "No puedes eliminar este departamento", "You cannot remove this department": "No puedes eliminar este departamento",
"The extension must be unique": "La extensión debe ser unica", "The extension must be unique": "La extensión debe ser unica",
@ -102,8 +102,8 @@
"You can't delete a confirmed order": "No puedes borrar un pedido confirmado", "You can't delete a confirmed order": "No puedes borrar un pedido confirmado",
"The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto", "The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto",
"Invalid quantity": "Cantidad invalida", "Invalid quantity": "Cantidad invalida",
"This postal code is not valid": "This postal code is not valid", "This postal code is not valid": "Este código postal no es válido",
"is invalid": "is invalid", "is invalid": "es inválido",
"The postcode doesn't exist. Please enter a correct one": "El código postal no existe. Por favor, introduce uno correcto", "The postcode doesn't exist. Please enter a correct one": "El código postal no existe. Por favor, introduce uno correcto",
"The department name can't be repeated": "El nombre del departamento no puede repetirse", "The department name can't be repeated": "El nombre del departamento no puede repetirse",
"This phone already exists": "Este teléfono ya existe", "This phone already exists": "Este teléfono ya existe",
@ -112,8 +112,8 @@
"You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada", "You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada",
"You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero", "You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero",
"You should specify a date": "Debes especificar una fecha", "You should specify a date": "Debes especificar una fecha",
"You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fín", "You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fin",
"Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fín", "Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fin",
"You should mark at least one week day": "Debes marcar al menos un día de la semana", "You should mark at least one week day": "Debes marcar al menos un día de la semana",
"Swift / BIC can't be empty": "Swift / BIC no puede estar vacío", "Swift / BIC can't be empty": "Swift / BIC no puede estar vacío",
"Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios", "Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios",
@ -144,15 +144,15 @@
"Unable to clone this travel": "No ha sido posible clonar este travel", "Unable to clone this travel": "No ha sido posible clonar este travel",
"This thermograph id already exists": "La id del termógrafo ya existe", "This thermograph id already exists": "La id del termógrafo ya existe",
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante", "Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante",
"ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED", "ORDER_ALREADY_CONFIRMED": "ORDEN YA CONFIRMADA",
"Invalid password": "Invalid password", "Invalid password": "Invalid password",
"Password does not meet requirements": "La contraseña no cumple los requisitos", "Password does not meet requirements": "La contraseña no cumple los requisitos",
"Role already assigned": "Role already assigned", "Role already assigned": "Rol ya asignado",
"Invalid role name": "Invalid role name", "Invalid role name": "Nombre de rol no válido",
"Role name must be written in camelCase": "Role name must be written in camelCase", "Role name must be written in camelCase": "El nombre del rol debe escribirse en camelCase",
"Email already exists": "Email already exists", "Email already exists": "El correo ya existe",
"User already exists": "User already exists", "User already exists": "El/La usuario/a ya existe",
"Absence change notification on the labour calendar": "Notificacion de cambio de ausencia en el calendario laboral", "Absence change notification on the labour calendar": "Notificación de cambio de ausencia en el calendario laboral",
"Record of hours week": "Registro de horas semana {{week}} año {{year}} ", "Record of hours week": "Registro de horas semana {{week}} año {{year}} ",
"Created absence": "El empleado <strong>{{author}}</strong> ha añadido una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> para el día {{dated}}.", "Created absence": "El empleado <strong>{{author}}</strong> ha añadido una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> para el día {{dated}}.",
"Deleted absence": "El empleado <strong>{{author}}</strong> ha eliminado una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> del día {{dated}}.", "Deleted absence": "El empleado <strong>{{author}}</strong> ha eliminado una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> del día {{dated}}.",
@ -317,6 +317,9 @@
"The ticket doesn't exist.": "No existe el ticket.", "The ticket doesn't exist.": "No existe el ticket.",
"Social name should be uppercase": "La razón social debe ir en mayúscula", "Social name should be uppercase": "La razón social debe ir en mayúscula",
"Street should be uppercase": "La dirección fiscal debe ir en mayúscula", "Street should be uppercase": "La dirección fiscal debe ir en mayúscula",
"Ticket without Route": "Ticket sin ruta",
"Select a different client": "Seleccione un cliente distinto",
"Fill all the fields": "Rellene todos los campos",
"The response is not a PDF": "La respuesta no es un PDF", "The response is not a PDF": "La respuesta no es un PDF",
"Ticket without Route": "Ticket sin ruta", "Ticket without Route": "Ticket sin ruta",
"Booking completed": "Reserva completada", "Booking completed": "Reserva completada",

View File

@ -43,9 +43,8 @@ module.exports = Self => {
Self.claimPickupEmail = async ctx => { Self.claimPickupEmail = async ctx => {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const $t = ctx.req.__; // $translate const $t = ctx.req.__; // $translate
const origin = ctx.req.headers.origin; const url = await Self.app.models.Url.getUrl();
const args = Object.assign({}, ctx.args); const args = Object.assign({}, ctx.args);
const params = { const params = {
@ -70,9 +69,8 @@ module.exports = Self => {
const message = $t('Claim pickup order sent', { const message = $t('Claim pickup order sent', {
claimId: args.id, claimId: args.id,
clientName: claim.client().name, clientName: claim.client().name,
claimUrl: `${origin}/#!/claim/${args.id}/summary`, claimUrl: `${url}claim/${args.id}/summary`,
}); });
const salesPersonId = claim.client().salesPersonFk; const salesPersonId = claim.client().salesPersonFk;
if (salesPersonId) if (salesPersonId)
await models.Chat.sendCheckingPresence(ctx, salesPersonId, message); await models.Chat.sendCheckingPresence(ctx, salesPersonId, message);

View File

@ -94,13 +94,13 @@ module.exports = Self => {
const salesPerson = ticket.client().salesPersonUser(); const salesPerson = ticket.client().salesPersonUser();
if (salesPerson) { if (salesPerson) {
const origin = ctx.req.headers.origin; const url = await Self.app.models.Url.getUrl();
const message = $t('Created claim', { const message = $t('Created claim', {
claimId: newClaim.id, claimId: newClaim.id,
ticketId: ticketId, ticketId: ticketId,
ticketUrl: `${origin}/#!/ticket/${ticketId}/sale`, ticketUrl: `${url}ticket/${ticketId}/sale`,
claimUrl: `${origin}/#!/claim/${newClaim.id}/summary`, claimUrl: `${url}claim/${newClaim.id}/summary`,
changes: changesMade changes: changesMade
}); });
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message); await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);

View File

@ -56,15 +56,15 @@ module.exports = Self => {
const salesPerson = sale.ticket().client().salesPersonUser(); const salesPerson = sale.ticket().client().salesPersonUser();
if (salesPerson) { if (salesPerson) {
const nickname = address && address.nickname || destination.description; const nickname = address && address.nickname || destination.description;
const origin = ctx.req.headers.origin; const url = await Self.app.models.Url.getUrl();
const message = $t('Sent units from ticket', { const message = $t('Sent units from ticket', {
quantity: sale.quantity, quantity: sale.quantity,
concept: sale.concept, concept: sale.concept,
itemId: sale.itemFk, itemId: sale.itemFk,
ticketId: sale.ticketFk, ticketId: sale.ticketFk,
nickname: nickname, nickname: nickname,
ticketUrl: `${origin}/#!/ticket/${sale.ticketFk}/sale`, ticketUrl: `${url}ticket/${sale.ticketFk}/sale`,
itemUrl: `${origin}/#!/item/${sale.itemFk}/summary` itemUrl: `${url}item/${sale.itemFk}/summary`
}); });
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message); await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
} }

View File

@ -2,7 +2,9 @@ const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
describe('Update Claim', () => { describe('Update Claim', () => {
let url;
beforeAll(async() => { beforeAll(async() => {
url = await app.models.Url.getUrl();
const activeCtx = { const activeCtx = {
accessToken: {userId: 9}, accessToken: {userId: 9},
http: { http: {
@ -29,7 +31,6 @@ describe('Update Claim', () => {
it(`should throw an error as the user doesn't have rights`, async() => { it(`should throw an error as the user doesn't have rights`, async() => {
const tx = await app.models.Claim.beginTransaction({}); const tx = await app.models.Claim.beginTransaction({});
let error; let error;
try { try {
@ -77,7 +78,7 @@ describe('Update Claim', () => {
const ctx = { const ctx = {
req: { req: {
accessToken: {userId: claimManagerId}, accessToken: {userId: claimManagerId},
headers: {origin: 'http://localhost'} headers: {origin: url}
}, },
args: { args: {
observation: 'valid observation', observation: 'valid observation',
@ -118,7 +119,7 @@ describe('Update Claim', () => {
const ctx = { const ctx = {
req: { req: {
accessToken: {userId: claimManagerId}, accessToken: {userId: claimManagerId},
headers: {origin: 'http://localhost'} headers: {origin: url}
}, },
args: { args: {
observation: 'valid observation', observation: 'valid observation',

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