Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2266_refactor_gulpfile_docker
This commit is contained in:
commit
477b1c8e1e
|
@ -12,11 +12,23 @@ module.exports = Self => {
|
||||||
message: `A client with that Web User name already exists`
|
message: `A client with that Web User name already exists`
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.observe('before save', (ctx, next) => {
|
Self.observe('before save', async function(ctx) {
|
||||||
if (ctx.currentInstance && ctx.currentInstance.id && ctx.data && ctx.data.password)
|
if (ctx.currentInstance && ctx.currentInstance.id && ctx.data && ctx.data.password)
|
||||||
ctx.data.password = md5(ctx.data.password);
|
ctx.data.password = md5(ctx.data.password);
|
||||||
|
|
||||||
next();
|
if (!ctx.isNewInstance && ctx.data && (ctx.data.name || ctx.data.active)) {
|
||||||
|
let instance = JSON.parse(JSON.stringify(ctx.currentInstance));
|
||||||
|
let userId = ctx.options.accessToken.userId;
|
||||||
|
let logRecord = {
|
||||||
|
originFk: ctx.currentInstance.id,
|
||||||
|
userFk: userId,
|
||||||
|
action: 'update',
|
||||||
|
changedModel: 'Account',
|
||||||
|
oldInstance: {name: instance.name, active: instance.active},
|
||||||
|
newInstance: ctx.data
|
||||||
|
};
|
||||||
|
await Self.app.models.ClientLog.create(logRecord);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.remoteMethod('getCurrentUserData', {
|
Self.remoteMethod('getCurrentUserData', {
|
||||||
|
|
|
@ -45,7 +45,7 @@ proc: BEGIN
|
||||||
|
|
||||||
IF vLanded IS NULL OR vZoneFk IS NULL THEN
|
IF vLanded IS NULL OR vZoneFk IS NULL THEN
|
||||||
|
|
||||||
CALL zone_getLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk);
|
CALL zone_getLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk, TRUE);
|
||||||
|
|
||||||
IF (SELECT COUNT(*) FROM tmp.zoneGetLanded LIMIT 1) = 0 THEN
|
IF (SELECT COUNT(*) FROM tmp.zoneGetLanded LIMIT 1) = 0 THEN
|
||||||
CALL util.throw('There is no zone for these parameters');
|
CALL util.throw('There is no zone for these parameters');
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `ticketCalculateClon`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `ticketCalculateClon`(IN vTicketNew INT, vTicketOld INT)
|
||||||
|
BEGIN
|
||||||
|
/*
|
||||||
|
* Recalcula los componentes un ticket clonado,
|
||||||
|
* las lineas a precio cero fuerza para que tengan precio, el resto lo respeta
|
||||||
|
* @param vTicketNew nuevo ticket clonado
|
||||||
|
* @param vTicketOld icket original, a partir del qual se clonara el nuevo
|
||||||
|
*/
|
||||||
|
DECLARE vShipped DATE;
|
||||||
|
DECLARE vClient INT;
|
||||||
|
DECLARE vWarehouse SMALLINT;
|
||||||
|
DECLARE vAgencyMode INT;
|
||||||
|
DECLARE vAddress INT;
|
||||||
|
DECLARE vLanded DATE;
|
||||||
|
DECLARE vAgency INT;
|
||||||
|
DECLARE vZoneFk INT;
|
||||||
|
|
||||||
|
REPLACE INTO orderTicket(orderFk,ticketFk)
|
||||||
|
SELECT orderFk, vTicketNew
|
||||||
|
FROM orderTicket
|
||||||
|
WHERE ticketFk = vTicketOld;
|
||||||
|
|
||||||
|
SELECT t.clientFk, t.warehouseFk, date(t.shipped), t.addressFk, t.agencyModeFk, t.landed, a.agencyFk, t.zoneFk
|
||||||
|
INTO vClient, vWarehouse, vShipped, vAddress, vAgencyMode, vLanded, vAgency, vZoneFk
|
||||||
|
FROM agencyMode a
|
||||||
|
JOIN ticket t ON t.agencyModeFk = a.id
|
||||||
|
WHERE t.id = vTicketNew;
|
||||||
|
|
||||||
|
IF vLanded IS NULL THEN
|
||||||
|
CALL zone_getLanded(vShipped, vAddress, vAgency, vWarehouse, TRUE);
|
||||||
|
UPDATE ticket t
|
||||||
|
JOIN tmp.zoneGetLanded zgl ON t.warehouseFk = zgl.warehouseFk
|
||||||
|
SET t.landed = zgl.landed,
|
||||||
|
t.zone = zgl.zoneFk
|
||||||
|
WHERE t.id = vTicketNew;
|
||||||
|
|
||||||
|
SELECT zoneFk INTO vZoneFk FROM tmp.zoneGetLanded LIMIT 1;
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.zoneGetLanded;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- rellena la tabla tmp.buyUltimate con la ultima compra
|
||||||
|
CALL buyUltimate(vWarehouse, vShipped);
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticketLot
|
||||||
|
SELECT vWarehouse warehouseFk, NULL available, s.itemFk, bu.buyFk, vZoneFk zoneFk
|
||||||
|
FROM sale s
|
||||||
|
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
|
||||||
|
WHERE s.ticketFk = vTicketOld GROUP BY s.itemFk;
|
||||||
|
|
||||||
|
CALL catalog_componentPrepare();
|
||||||
|
CALL catalog_componentCalculate(vZoneFk, vAddress, vAgencyMode, vWarehouse);
|
||||||
|
|
||||||
|
-- Bionizamos lineas con Preu = 0
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
|
||||||
|
CREATE TEMPORARY TABLE tmp.sale
|
||||||
|
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
|
||||||
|
SELECT s.id saleFk, vWarehouse warehouseFk
|
||||||
|
FROM sale s
|
||||||
|
JOIN ticket t on t.id = s.ticketFk WHERE s.ticketFk = vTicketNew AND s.price = 0;
|
||||||
|
|
||||||
|
CALL ticketComponentUpdateSale(1);
|
||||||
|
|
||||||
|
-- Bionizamos lineas con Preu > 0
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
|
||||||
|
CREATE TEMPORARY TABLE tmp.sale
|
||||||
|
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
|
||||||
|
SELECT s.id saleFk, vWarehouse warehouseFk
|
||||||
|
FROM sale s
|
||||||
|
JOIN ticket t on t.id = s.ticketFk WHERE s.ticketFk = vTicketNew
|
||||||
|
AND s.price > 0;
|
||||||
|
|
||||||
|
CALL ticketComponentUpdateSale(6);
|
||||||
|
|
||||||
|
-- Log
|
||||||
|
CALL `logAdd`(vTicketNew, 'update', ' ticket' , 'Bioniza Ticket');
|
||||||
|
|
||||||
|
-- Limpieza
|
||||||
|
CALL catalog_componentPurge();
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS
|
||||||
|
tmp.buyUltimate,
|
||||||
|
tmp.sale,
|
||||||
|
tmp.zoneGetLanded;
|
||||||
|
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `ticket_cloneWeekly`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_cloneWeekly`(IN vWeek INT)
|
||||||
|
BEGIN
|
||||||
|
DECLARE vIsDone BOOL;
|
||||||
|
DECLARE vLanding DATE;
|
||||||
|
DECLARE vShipment DATE;
|
||||||
|
DECLARE vWarehouse INT;
|
||||||
|
DECLARE vTicket INT;
|
||||||
|
DECLARE vWeekDay INT;
|
||||||
|
DECLARE vClient INT;
|
||||||
|
DECLARE vEmpresa INT;
|
||||||
|
DECLARE vAddressFk INT;
|
||||||
|
DECLARE vAgencyModeFk INT;
|
||||||
|
DECLARE vNewTicket INT;
|
||||||
|
DECLARE vYear INT;
|
||||||
|
|
||||||
|
DECLARE rsTicket CURSOR FOR
|
||||||
|
SELECT tw.ticketFk, weekDay, t.clientFk, t.warehouseFk, t.companyFk, t.addressFk, tw.agencyModeFk
|
||||||
|
FROM ticketWeekly tw
|
||||||
|
JOIN ticket t ON tt.ticketFk = t.id;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vIsDone = TRUE;
|
||||||
|
|
||||||
|
SET vYear = YEAR(CURDATE()) + IF(vWeek < WEEK(CURDATE()),1, 0);
|
||||||
|
|
||||||
|
OPEN rsTicket;
|
||||||
|
|
||||||
|
myLoop: LOOP
|
||||||
|
BEGIN
|
||||||
|
DECLARE vError TEXT;
|
||||||
|
DECLARE vSalesPersonEmail VARCHAR(150);
|
||||||
|
DECLARE vMailSent BOOL;
|
||||||
|
DECLARE vSubject VARCHAR(150);
|
||||||
|
DECLARE vMessage TEXT;
|
||||||
|
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
GET DIAGNOSTICS CONDITION 1
|
||||||
|
vError = MESSAGE_TEXT;
|
||||||
|
END;
|
||||||
|
|
||||||
|
SET vIsDone = FALSE;
|
||||||
|
FETCH rsTicket INTO vTicket, vWeekDay, vClient, vWarehouse, vEmpresa, vAddressFk, vAgencyModeFk;
|
||||||
|
|
||||||
|
IF vIsDone THEN
|
||||||
|
|
||||||
|
LEAVE myLoop;
|
||||||
|
END IF;
|
||||||
|
SELECT date INTO vShipment
|
||||||
|
FROM `time`
|
||||||
|
WHERE `year` = vYear AND `week` = vWeek
|
||||||
|
AND WEEKDAY(date) = vWeekDay;
|
||||||
|
|
||||||
|
-- busca si el ticket ya ha sido clonado
|
||||||
|
IF (SELECT COUNT(*) FROM vn.ticket tOrig
|
||||||
|
JOIN vn.sale saleOrig ON tOrig.id = saleOrig.ticketFk
|
||||||
|
JOIN vn.saleCloned sc ON sc.saleOriginalFk = saleOrig.id
|
||||||
|
JOIN vn.sale saleClon ON saleClon.id = sc.saleClonedFk
|
||||||
|
JOIN vn.ticket tClon ON tClon.id = saleClon.ticketFk
|
||||||
|
WHERE tOrig.id = vTicket AND DATE(tClon.shipped) = vShipment) > 0
|
||||||
|
THEN
|
||||||
|
ITERATE myLoop;
|
||||||
|
END IF;
|
||||||
|
CALL vn.zone_getLanded(vShipment, vAddressFk, vAgencyModeFk, vWarehouse, TRUE);
|
||||||
|
|
||||||
|
SELECT landed INTO vLanding from tmp.zoneGetLanded LIMIT 1;
|
||||||
|
|
||||||
|
CALL vn.ticketCreateWithoutZone(vClient, vShipment, vWarehouse, vEmpresa, vAddressFk, vAgencyModeFk, NULL, vLanding, account.userGetId(), vNewTicket);
|
||||||
|
|
||||||
|
IF (vLanding IS NULL) THEN
|
||||||
|
|
||||||
|
SELECT e.email INTO vSalesPersonEmail
|
||||||
|
FROM vn.client c
|
||||||
|
JOIN vn.worker sp ON sp.id = c.salesPersonFk
|
||||||
|
JOIN account.emailUser e ON e.userFk = sp.userFk
|
||||||
|
WHERE c.id = vClient;
|
||||||
|
|
||||||
|
SET vSubject = CONCAT('Turnos - No se ha podido clonar correctamente el ticket ', vTicket,
|
||||||
|
' para el dia: ', vShipment);
|
||||||
|
SET vMessage = CONCAT('No se ha podido clonar el ticket ', vTicket,
|
||||||
|
' para el dia: ', vShipment,
|
||||||
|
' porque no hay una zona de envío disponible. Se ha creado el ticket: ', vNewTicket,
|
||||||
|
' pero ha que revisar las fechas y la agencia');
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO vMailSent
|
||||||
|
FROM vn.mail
|
||||||
|
WHERE sender = vSalesPersonEmail
|
||||||
|
AND subject = vSubject;
|
||||||
|
|
||||||
|
IF NOT vMailSent THEN
|
||||||
|
INSERT INTO vn.mail (sender,`subject`,body)
|
||||||
|
VALUES (vSalesPersonEmail, vSubject, vMessage);
|
||||||
|
END IF;
|
||||||
|
CALL vn.ticketStateUpdate (vNewTicket, 'FIXING');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
INSERT INTO vn.sale (ticketFk, itemFk, concept, quantity, price, discount, priceFixed, isPriceFixed)
|
||||||
|
SELECT vNewTicket, saleOrig.itemFk , saleOrig.concept , saleOrig.quantity, saleOrig.price , saleOrig.discount, saleOrig.priceFixed, saleOrig.isPriceFixed
|
||||||
|
FROM vn.ticket tOrig
|
||||||
|
JOIN vn.sale saleOrig ON tOrig.id = saleOrig.ticketFk
|
||||||
|
LEFT JOIN vn.saleCloned sc ON sc.saleOriginalFk = saleOrig.id
|
||||||
|
LEFT JOIN vn.sale saleClon ON saleClon.id = sc.saleClonedFk
|
||||||
|
LEFT JOIN vn.ticket tClon ON tClon.id = saleClon.ticketFk AND DATE(tClon.shipped) = vShipment
|
||||||
|
WHERE tOrig.id = vTicket AND saleClon.id IS NULL;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.saleCloned(saleOriginalFk, saleClonedFk)
|
||||||
|
SELECT saleOriginal.id, saleClon.id
|
||||||
|
FROM vn.sale saleOriginal
|
||||||
|
JOIN vn.sale saleClon ON saleOriginal.itemFk = saleClon.itemFk AND saleOriginal.quantity = saleClon.quantity
|
||||||
|
WHERE saleOriginal.ticketFk = vTicket AND saleClon.ticketFk = vNewTicket;
|
||||||
|
|
||||||
|
INSERT INTO ticketRequest (description, ordered, shipped, salesPersonCode, buyerCode, quantity, price,
|
||||||
|
itemFk ,clientFk, response, total, buyed, saleFk)
|
||||||
|
SELECT tr.description, tr.ordered, tr.shipped, tr.salesPersonCode, tr.buyerCode, tr.quantity, tr.price,
|
||||||
|
tr.itemFk, tr.clientFk, tr.response, tr.total, tr.buyed, tr.saleFk
|
||||||
|
FROM sale s JOIN ticketRequest tr ON tr.saleFk = s.id
|
||||||
|
JOIN sale s2 ON s.concept = s2.concept AND s.quantity = s2.quantity AND m.Id_Article = m2.Id_Article
|
||||||
|
WHERE s.ticketFk = vTicket AND s2.ticketFk = vNewTicket;
|
||||||
|
|
||||||
|
CALL vn.ticketCalculateClon(vNewTicket, vTicket);
|
||||||
|
END;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
CLOSE rsTicket;
|
||||||
|
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `ticket_recalcComponents`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_recalcComponents`(IN vTicketFk BIGINT, vIsTicketEditable BOOLEAN)
|
||||||
|
proc: BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Este procedimiento recalcula los componentes de un ticket,
|
||||||
|
* eliminando los componentes existentes e insertandolos de nuevo
|
||||||
|
*
|
||||||
|
* @param vTicketFk Id del ticket
|
||||||
|
* @param vIsTicketEditable si no se quiere forzar llamar con NULL
|
||||||
|
*/
|
||||||
|
DECLARE vShipped DATE;
|
||||||
|
DECLARE vWarehouseFk SMALLINT;
|
||||||
|
DECLARE vAgencyModeFk INT;
|
||||||
|
DECLARE vAddressFk INT;
|
||||||
|
DECLARE vLanded DATE;
|
||||||
|
DECLARE vZoneFk INTEGER;
|
||||||
|
|
||||||
|
IF vIsTicketEditable IS NULL THEN
|
||||||
|
SELECT IFNULL(ts.alertLevel,0) = 0 AND IFNULL(t.refFk,'') = ''
|
||||||
|
INTO vIsTicketEditable
|
||||||
|
FROM ticket t LEFT JOIN ticketState ts ON t.id = ts.ticket
|
||||||
|
WHERE id = vTicketFk;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT t.warehouseFk,
|
||||||
|
t.shipped,
|
||||||
|
t.addressFk,
|
||||||
|
t.agencyModeFk,
|
||||||
|
t.landed,
|
||||||
|
t.zoneFk
|
||||||
|
INTO vWarehouseFk, vShipped, vAddressFk, vAgencyModeFk, vLanded, vZoneFk
|
||||||
|
FROM ticket t LEFT JOIN ticketState ts ON t.id = ts.ticket
|
||||||
|
WHERE t.id = vTicketFk;
|
||||||
|
|
||||||
|
IF vLanded IS NULL OR vZoneFk IS NULL THEN
|
||||||
|
|
||||||
|
CALL zone_getLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk, TRUE);
|
||||||
|
|
||||||
|
IF (SELECT COUNT(*) FROM tmp.zoneGetLanded LIMIT 1) = 0 THEN
|
||||||
|
CALL util.throw('There is no zone for these parameters');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
UPDATE ticket t
|
||||||
|
SET t.landed = (SELECT landed FROM tmp.zoneGetLanded LIMIT 1)
|
||||||
|
WHERE t.id = vTicketFk AND t.landed IS NULL;
|
||||||
|
|
||||||
|
IF vZoneFk IS NULL THEN
|
||||||
|
SELECT zoneFk INTO vZoneFk FROM tmp.zoneGetLanded LIMIT 1;
|
||||||
|
UPDATE ticket t
|
||||||
|
SET t.zoneFk = vZoneFk
|
||||||
|
WHERE t.id = vTicketFk AND t.zoneFk IS NULL;
|
||||||
|
END IF;
|
||||||
|
DROP TEMPORARY TABLE tmp.zoneGetLanded;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- rellena la tabla buyUltimate con la ultima compra
|
||||||
|
CALL buyUltimate (vWarehouseFk, vShipped);
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticketLot
|
||||||
|
SELECT vWarehouseFk warehouseFk, NULL available,
|
||||||
|
s.itemFk, bu.buyFk, vZoneFk zoneFk
|
||||||
|
FROM sale s
|
||||||
|
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
|
||||||
|
WHERE s.ticketFk = vTicketFk
|
||||||
|
GROUP BY s.itemFk;
|
||||||
|
|
||||||
|
CALL catalog_componentPrepare();
|
||||||
|
CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
|
||||||
|
CREATE TEMPORARY TABLE tmp.sale
|
||||||
|
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
|
||||||
|
SELECT id saleFk, vWarehouseFk warehouseFk
|
||||||
|
FROM sale s
|
||||||
|
WHERE s.ticketFk = vTicketFk;
|
||||||
|
|
||||||
|
-- si el ticket esta facturado, respeta los precios
|
||||||
|
CALL ticketComponentUpdateSale(IF(vIsTicketEditable, 1, 6));
|
||||||
|
|
||||||
|
CALL catalog_componentPurge();
|
||||||
|
DROP TEMPORARY TABLE
|
||||||
|
tmp.buyUltimate,
|
||||||
|
tmp.sale;
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,40 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `zone_getLanded`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getLanded`(vShipped DATE, vAddressFk INT, vAgencyModeFk INT, vWarehouseFk INT, vShowExpiredZones BOOLEAN)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Devuelve una tabla temporal con el dia de recepcion para vShipped.
|
||||||
|
*
|
||||||
|
* @param vShipped Fecha de preparacion de mercancia
|
||||||
|
* @param vAddressFk Id de consignatario, %NULL para recogida
|
||||||
|
* @param vAgencyModeFk Id agencia
|
||||||
|
* @param vWarehouseFk vWarehouseFk
|
||||||
|
* @table tmp.zoneGetLanded Datos de recepción
|
||||||
|
*/
|
||||||
|
|
||||||
|
CALL zone_getFromGeo(address_getGeo(vAddressFk));
|
||||||
|
CALL zone_getOptionsForShipment(vShipped, vShowExpiredZones);
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.zoneGetLanded;
|
||||||
|
CREATE TEMPORARY TABLE tmp.zoneGetLanded
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT vWarehouseFk warehouseFk,
|
||||||
|
TIMESTAMPADD(DAY,zo.travelingDays, vShipped) landed,
|
||||||
|
zo.zoneFk
|
||||||
|
FROM tmp.zoneOption zo
|
||||||
|
JOIN zone z ON z.id = zo.zoneFk
|
||||||
|
JOIN zoneWarehouse zw ON zw.zoneFk = z.id
|
||||||
|
WHERE agencyModeFk = vAgencyModeFk
|
||||||
|
AND zw.warehouseFk = vWarehouseFk;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE
|
||||||
|
tmp.zone,
|
||||||
|
tmp.zoneOption;
|
||||||
|
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -11,12 +11,14 @@ describe('zone zone_getLanded()', () => {
|
||||||
let params = {
|
let params = {
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: 7,
|
agencyModeFk: 7,
|
||||||
warehouseFk: 1};
|
warehouseFk: 1,
|
||||||
|
showExpiredZones: true};
|
||||||
|
|
||||||
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(CURDATE(), INTERVAL -1 DAY), ?, ?, ?)', [
|
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(CURDATE(), INTERVAL -1 DAY), ?, ?, ?, ?)', [
|
||||||
params.addressFk,
|
params.addressFk,
|
||||||
params.agencyModeFk,
|
params.agencyModeFk,
|
||||||
params.warehouseFk
|
params.warehouseFk,
|
||||||
|
params.showExpiredZones
|
||||||
|
|
||||||
]);
|
]);
|
||||||
stmts.push(stmt);
|
stmts.push(stmt);
|
||||||
|
@ -42,12 +44,14 @@ describe('zone zone_getLanded()', () => {
|
||||||
let params = {
|
let params = {
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: 7,
|
agencyModeFk: 7,
|
||||||
warehouseFk: 1};
|
warehouseFk: 1,
|
||||||
|
showExpiredZones: false};
|
||||||
|
|
||||||
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(CURDATE(), INTERVAL +2 DAY), ?, ?, ?)', [
|
stmt = new ParameterizedSQL('CALL zone_getLanded(DATE_ADD(CURDATE(), INTERVAL +2 DAY), ?, ?, ?, ?)', [
|
||||||
params.addressFk,
|
params.addressFk,
|
||||||
params.agencyModeFk,
|
params.agencyModeFk,
|
||||||
params.warehouseFk
|
params.warehouseFk,
|
||||||
|
params.showExpiredZones
|
||||||
|
|
||||||
]);
|
]);
|
||||||
stmts.push(stmt);
|
stmts.push(stmt);
|
||||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
||||||
ticketsButton: '.modules-menu [ui-sref="ticket.index"]',
|
ticketsButton: '.modules-menu [ui-sref="ticket.index"]',
|
||||||
invoiceOutButton: '.modules-menu [ui-sref="invoiceOut.index"]',
|
invoiceOutButton: '.modules-menu [ui-sref="invoiceOut.index"]',
|
||||||
claimsButton: '.modules-menu [ui-sref="claim.index"]',
|
claimsButton: '.modules-menu [ui-sref="claim.index"]',
|
||||||
returnToModuleIndexButton: 'a[ui-sref="order.index"]',
|
returnToModuleIndexButton: 'a[name="goToModuleIndex"]',
|
||||||
homeButton: 'vn-topbar > div.side.start > a',
|
homeButton: 'vn-topbar > div.side.start > a',
|
||||||
userLocalWarehouse: '.user-popover vn-autocomplete[ng-model="$ctrl.localWarehouseFk"]',
|
userLocalWarehouse: '.user-popover vn-autocomplete[ng-model="$ctrl.localWarehouseFk"]',
|
||||||
userLocalBank: '.user-popover vn-autocomplete[ng-model="$ctrl.localBankFk"]',
|
userLocalBank: '.user-popover vn-autocomplete[ng-model="$ctrl.localBankFk"]',
|
||||||
|
@ -365,7 +365,8 @@ export default {
|
||||||
firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3)',
|
firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3)',
|
||||||
firstSaleDiscount: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6)',
|
firstSaleDiscount: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6)',
|
||||||
invoiceOutRef: 'vn-ticket-summary > vn-card > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(7) > section > span',
|
invoiceOutRef: 'vn-ticket-summary > vn-card > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(7) > section > span',
|
||||||
setOk: 'vn-ticket-summary vn-button[label="SET OK"] > button'
|
setOk: 'vn-ticket-summary vn-button[label="SET OK"] > button',
|
||||||
|
descriptorTicketId: 'vn-ticket-descriptor > vn-descriptor-content > div > div.body > div.top > div'
|
||||||
},
|
},
|
||||||
ticketsIndex: {
|
ticketsIndex: {
|
||||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||||
|
|
|
@ -4,6 +4,9 @@ import getBrowser from '../../helpers/puppeteer';
|
||||||
describe('Ticket create path', () => {
|
describe('Ticket create path', () => {
|
||||||
let browser;
|
let browser;
|
||||||
let page;
|
let page;
|
||||||
|
let nextMonth = new Date();
|
||||||
|
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
||||||
|
let stowawayTicketId;
|
||||||
|
|
||||||
beforeAll(async() => {
|
beforeAll(async() => {
|
||||||
browser = await getBrowser();
|
browser = await getBrowser();
|
||||||
|
@ -21,13 +24,9 @@ describe('Ticket create path', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should succeed to create a ticket', async() => {
|
it('should succeed to create a ticket', async() => {
|
||||||
const nextMonth = new Date();
|
await page.autocompleteSearch(selectors.createTicketView.client, 'Clark Kent');
|
||||||
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.createTicketView.client, 'Tony Stark');
|
|
||||||
await page.autocompleteSearch(selectors.createTicketView.address, 'Tony Stark');
|
|
||||||
await page.pickDate(selectors.createTicketView.deliveryDate, nextMonth);
|
await page.pickDate(selectors.createTicketView.deliveryDate, nextMonth);
|
||||||
await page.autocompleteSearch(selectors.createTicketView.warehouse, 'Warehouse One');
|
await page.autocompleteSearch(selectors.createTicketView.warehouse, 'Warehouse Two');
|
||||||
await page.autocompleteSearch(selectors.createTicketView.agency, 'Silla247');
|
await page.autocompleteSearch(selectors.createTicketView.agency, 'Silla247');
|
||||||
await page.waitToClick(selectors.createTicketView.createButton);
|
await page.waitToClick(selectors.createTicketView.createButton);
|
||||||
const message = await page.waitForSnackbar();
|
const message = await page.waitForSnackbar();
|
||||||
|
@ -37,5 +36,53 @@ describe('Ticket create path', () => {
|
||||||
|
|
||||||
it('should check the url is now the summary of the ticket', async() => {
|
it('should check the url is now the summary of the ticket', async() => {
|
||||||
await page.waitForState('ticket.card.summary');
|
await page.waitForState('ticket.card.summary');
|
||||||
|
stowawayTicketId = await page.waitToGetProperty(selectors.ticketSummary.descriptorTicketId, 'innerText');
|
||||||
|
stowawayTicketId = stowawayTicketId.substring(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should again open the new ticket form', async() => {
|
||||||
|
await page.waitToClick(selectors.globalItems.returnToModuleIndexButton);
|
||||||
|
await page.waitToClick(selectors.ticketsIndex.newTicketButton);
|
||||||
|
await page.waitForState('ticket.create');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should succeed to create another ticket for the same client', async() => {
|
||||||
|
await page.autocompleteSearch(selectors.createTicketView.client, 'Clark Kent');
|
||||||
|
await page.pickDate(selectors.createTicketView.deliveryDate, nextMonth);
|
||||||
|
await page.autocompleteSearch(selectors.createTicketView.warehouse, 'Warehouse One');
|
||||||
|
await page.autocompleteSearch(selectors.createTicketView.agency, 'Silla247');
|
||||||
|
await page.waitToClick(selectors.createTicketView.createButton);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
|
expect(message.type).toBe('success');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the url is now the summary of the created ticket', async() => {
|
||||||
|
await page.waitForState('ticket.card.summary');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should make the previously created ticket the stowaway of the current ticket', async() => {
|
||||||
|
await page.waitToClick(selectors.ticketDescriptor.moreMenu);
|
||||||
|
await page.waitToClick(selectors.ticketDescriptor.moreMenuAddStowaway);
|
||||||
|
await page.waitToClick(selectors.ticketDescriptor.addStowawayDialogFirstTicket);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
|
expect(message.type).toBe('success');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete the current ticket', async() => {
|
||||||
|
await page.waitToClick(selectors.ticketDescriptor.moreMenu);
|
||||||
|
await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket);
|
||||||
|
await page.waitToClick(selectors.ticketDescriptor.acceptDeleteButton);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
|
expect(message.type).toBe('success');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should search for the stowaway ticket of the previously deleted ticket', async() => {
|
||||||
|
await page.accessToSearchResult(stowawayTicketId);
|
||||||
|
const result = await page.countElement(selectors.ticketDescriptor.shipButton);
|
||||||
|
|
||||||
|
expect(result).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<section vn-id="contextmenu">
|
||||||
|
<vn-menu vn-id="menu">
|
||||||
|
<div ng-transclude="menu"></div>
|
||||||
|
</vn-menu>
|
||||||
|
</section>
|
|
@ -0,0 +1,224 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import {buildFilter} from 'vn-loopback/util/filter';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
export default class Contextmenu {
|
||||||
|
constructor($element, $, $transclude) {
|
||||||
|
this.$element = $element;
|
||||||
|
this.element = $element[0];
|
||||||
|
this.$ = $;
|
||||||
|
this.$transclude = $transclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
get targets() {
|
||||||
|
return this._targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
set targets(value) {
|
||||||
|
this._targets = value;
|
||||||
|
|
||||||
|
if (!value) return;
|
||||||
|
|
||||||
|
for (let selector of value) {
|
||||||
|
const target = document.querySelector(selector);
|
||||||
|
if (!target) continue;
|
||||||
|
|
||||||
|
target.addEventListener('contextmenu', event => {
|
||||||
|
this.target = event.target;
|
||||||
|
|
||||||
|
if (!event.defaultPrevented)
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (!this.isFilterEnabled()) return;
|
||||||
|
|
||||||
|
const parent = this.$.contextmenu;
|
||||||
|
parent.style.top = event.pageY + 'px';
|
||||||
|
parent.style.left = event.pageX + 'px';
|
||||||
|
|
||||||
|
this.$.menu.show(parent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get row() {
|
||||||
|
if (!this.target) return null;
|
||||||
|
|
||||||
|
return this.target.closest('vn-tr, .vn-tr');
|
||||||
|
}
|
||||||
|
|
||||||
|
get rowIndex() {
|
||||||
|
if (!this.row) return null;
|
||||||
|
const table = this.row.closest('vn-table, .vn-table');
|
||||||
|
const tBody = table.querySelector('vn-tbody, .vn-tbody');
|
||||||
|
const rows = tBody.querySelectorAll('vn-tr, .vn-tr');
|
||||||
|
|
||||||
|
return Array.from(rows).findIndex(
|
||||||
|
rowItem => rowItem == this.row
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get rowData() {
|
||||||
|
const model = this.model;
|
||||||
|
const rowData = model.data[this.rowIndex];
|
||||||
|
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
|
||||||
|
get cell() {
|
||||||
|
if (!this.target) return null;
|
||||||
|
|
||||||
|
return this.target.closest('vn-td, .vn-td');
|
||||||
|
}
|
||||||
|
|
||||||
|
get cellIndex() {
|
||||||
|
if (!this.row) return null;
|
||||||
|
|
||||||
|
const cells = this.row.querySelectorAll('vn-td, .vn-td');
|
||||||
|
return Array.from(cells).findIndex(
|
||||||
|
cellItem => cellItem == this.cell
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get rowHeader() {
|
||||||
|
if (!this.row) return null;
|
||||||
|
|
||||||
|
const table = this.row.closest('vn-table, .vn-table');
|
||||||
|
const headerCells = table && table.querySelectorAll('vn-thead vn-th');
|
||||||
|
const headerCell = headerCells && headerCells[this.cellIndex];
|
||||||
|
|
||||||
|
return headerCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selected model field name
|
||||||
|
*
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
get fieldName() {
|
||||||
|
if (!this.rowHeader) return null;
|
||||||
|
|
||||||
|
return this.rowHeader.getAttribute('field');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selected field value
|
||||||
|
*
|
||||||
|
* @return {any}
|
||||||
|
*/
|
||||||
|
get fieldValue() {
|
||||||
|
return this.rowData[this.fieldName];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if filter is not disabled
|
||||||
|
*
|
||||||
|
* @return {Boolean}
|
||||||
|
*/
|
||||||
|
isFilterEnabled() {
|
||||||
|
if (!this.rowHeader) return true;
|
||||||
|
const isEnabled = this.rowHeader.getAttribute('filter-enabled');
|
||||||
|
|
||||||
|
return isEnabled != 'false';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if filter
|
||||||
|
* by selection is allowed
|
||||||
|
*
|
||||||
|
* @return {Boolean}
|
||||||
|
*/
|
||||||
|
isFilterAllowed() {
|
||||||
|
if (!this.target) return false;
|
||||||
|
const isTableCell = this.target.closest('vn-td, .vn-td');
|
||||||
|
|
||||||
|
return isTableCell && this.fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by current field selection
|
||||||
|
*/
|
||||||
|
filterBySelection() {
|
||||||
|
let where = {[this.fieldName]: this.fieldValue};
|
||||||
|
if (this.exprBuilder) {
|
||||||
|
where = buildFilter(where, (param, value) =>
|
||||||
|
this.exprBuilder({param, value})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.model.addFilter({where});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude by current field selection
|
||||||
|
*/
|
||||||
|
excludeSelection() {
|
||||||
|
let where = {[this.fieldName]: {neq: this.fieldValue}};
|
||||||
|
if (this.exprBuilder) {
|
||||||
|
where = buildFilter(where, (param, value) =>
|
||||||
|
this.exprBuilder({param, value})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.model.addFilter({where});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFilter() {
|
||||||
|
const userFilter = this.model.userFilter;
|
||||||
|
const userParams = this.model.userParams;
|
||||||
|
const where = userFilter.where;
|
||||||
|
|
||||||
|
let filterKey = this.fieldName;
|
||||||
|
if (this.exprBuilder) {
|
||||||
|
const param = this.exprBuilder({
|
||||||
|
param: filterKey,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
|
[filterKey] = Object.keys(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
const whereKeys = Object.keys(where);
|
||||||
|
for (let key of whereKeys)
|
||||||
|
removeProp(where, filterKey, key);
|
||||||
|
|
||||||
|
function removeProp(instance, findProp, prop) {
|
||||||
|
if (prop == findProp)
|
||||||
|
delete instance[prop];
|
||||||
|
|
||||||
|
if (prop === 'and') {
|
||||||
|
for (let [index, param] of instance[prop].entries()) {
|
||||||
|
const [key] = Object.keys(param);
|
||||||
|
if (key == findProp)
|
||||||
|
instance[prop].splice(index, 1);
|
||||||
|
|
||||||
|
if (param[key] instanceof Array)
|
||||||
|
removeProp(param, filterKey, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.model.applyFilter(userFilter, userParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all applied filters
|
||||||
|
*/
|
||||||
|
removeAllFilters() {
|
||||||
|
const userParams = this.model.userParams;
|
||||||
|
this.model.applyFilter(null, userParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Contextmenu.$inject = ['$element', '$scope', '$transclude'];
|
||||||
|
|
||||||
|
ngModule.vnComponent('vnContextmenu', {
|
||||||
|
controller: Contextmenu,
|
||||||
|
template: require('./index.html'),
|
||||||
|
bindings: {
|
||||||
|
targets: '<?',
|
||||||
|
model: '<?',
|
||||||
|
exprBuilder: '&?'
|
||||||
|
},
|
||||||
|
transclude: {
|
||||||
|
menu: '?slotMenu'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,3 @@
|
||||||
|
section[vn-id="contextmenu"] {
|
||||||
|
position: absolute
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="icons pre">
|
<div class="icons pre">
|
||||||
<vn-icon
|
<vn-icon ng-show="::$ctrl.clearDisabled != true"
|
||||||
icon="clear"
|
icon="clear"
|
||||||
translate-attr="{title: 'Clear'}"
|
translate-attr="{title: 'Clear'}"
|
||||||
ng-click="$ctrl.onClear($event)">
|
ng-click="$ctrl.onClear($event)">
|
||||||
|
|
|
@ -203,6 +203,7 @@ ngModule.vnComponent('vnField', {
|
||||||
type: '@?',
|
type: '@?',
|
||||||
autocomplete: '@?',
|
autocomplete: '@?',
|
||||||
placeholder: '@?',
|
placeholder: '@?',
|
||||||
|
clearDisabled: '<?',
|
||||||
value: '=?',
|
value: '=?',
|
||||||
info: '@?',
|
info: '@?',
|
||||||
required: '<?',
|
required: '<?',
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
describe('Component vnField', () => {
|
||||||
|
let $element;
|
||||||
|
let controller;
|
||||||
|
|
||||||
|
beforeEach(ngModule('vnCore'));
|
||||||
|
|
||||||
|
beforeEach(inject(($compile, $rootScope) => {
|
||||||
|
$element = $compile(`<vn-textfield></vn-textfield>`)($rootScope);
|
||||||
|
controller = $element.controller('vnTextfield');
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
$element.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove this block
|
||||||
|
describe('clearDisabled binding', () => {
|
||||||
|
it(`should enable the show property`, () => {
|
||||||
|
controller.clearDisabled = true;
|
||||||
|
|
||||||
|
expect(controller.clearDisabled).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -50,3 +50,4 @@ import './th';
|
||||||
import './treeview';
|
import './treeview';
|
||||||
import './wday-picker';
|
import './wday-picker';
|
||||||
import './datalist';
|
import './datalist';
|
||||||
|
import './contextmenu';
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
import Field from '../field';
|
import Field from '../field';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
export default class Textarea extends Field {
|
export default class Textarea extends Field {
|
||||||
constructor($element, $scope, $compile) {
|
constructor($element, $scope, $compile) {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
.vn-textarea {
|
||||||
|
& > .container {
|
||||||
|
& > .icons {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -259,6 +259,10 @@ module.exports = function(Self) {
|
||||||
removeUnloggable(definition, oldInstance);
|
removeUnloggable(definition, oldInstance);
|
||||||
removeUnloggable(definition, newInstance);
|
removeUnloggable(definition, newInstance);
|
||||||
|
|
||||||
|
// Prevent log with no new changes
|
||||||
|
const hasNewChanges = Object.keys(newInstance).length;
|
||||||
|
if (!hasNewChanges) return;
|
||||||
|
|
||||||
let logRecord = {
|
let logRecord = {
|
||||||
originFk: originId,
|
originFk: originId,
|
||||||
userFk: userFk,
|
userFk: userFk,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('regularizeClaim()', () => {
|
// #2304
|
||||||
|
xdescribe('regularizeClaim()', () => {
|
||||||
const claimFk = 1;
|
const claimFk = 1;
|
||||||
const pendentState = 1;
|
const pendentState = 1;
|
||||||
const resolvedState = 3;
|
const resolvedState = 3;
|
||||||
|
|
|
@ -76,8 +76,8 @@
|
||||||
<span
|
<span
|
||||||
ng-if="balance.isInvoice"
|
ng-if="balance.isInvoice"
|
||||||
title="{{'BILL' | translate: {ref: balance.ref} }}"
|
title="{{'BILL' | translate: {ref: balance.ref} }}"
|
||||||
vn-click-stop="invoiceOutDescriptor.show($event, balance)"
|
vn-click-stop="$ctrl.showInvoiceOutDescriptor($event, balance)"
|
||||||
ng-class="link">
|
class="link">
|
||||||
{{'BILL' | translate: {ref: balance.ref} }}
|
{{'BILL' | translate: {ref: balance.ref} }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
|
|
|
@ -72,6 +72,13 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showInvoiceOutDescriptor(event, balance) {
|
||||||
|
if (!balance.isInvoice) return;
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
|
|
||||||
|
this.$.invoiceOutDescriptor.show(event.target, balance.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope'];
|
Controller.$inject = ['$element', '$scope'];
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="consumerReportDialog.show()"
|
ng-click="consumerReportDialog.show()"
|
||||||
translate>
|
translate>
|
||||||
Send consumer report
|
View consumer report
|
||||||
</vn-item>
|
</vn-item>
|
||||||
</slot-menu>
|
</slot-menu>
|
||||||
<slot-body>
|
<slot-body>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Simple ticket: Ticket simple
|
Simple ticket: Ticket simple
|
||||||
Send consumer report: Enviar informe de consumo
|
View consumer report: Ver informe de consumo
|
||||||
From date: Fecha desde
|
From date: Fecha desde
|
||||||
To date: Fecha hasta
|
To date: Fecha hasta
|
|
@ -56,7 +56,7 @@
|
||||||
<div ng-transclude="btnTwo">
|
<div ng-transclude="btnTwo">
|
||||||
<vn-quick-link
|
<vn-quick-link
|
||||||
tooltip="Invoice ticket list"
|
tooltip="Invoice ticket list"
|
||||||
state="['ticket.card.summary', {id: $ctrl.invoiceOut.ref}]"
|
state="['ticket.index', {q: $ctrl.filter}]"
|
||||||
icon="icon-ticket">
|
icon="icon-ticket">
|
||||||
</vn-quick-link>
|
</vn-quick-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -22,6 +22,13 @@ class Controller extends Descriptor {
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('InvoiceOut booked')));
|
.then(() => this.vnApp.showSuccess(this.$t('InvoiceOut booked')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get filter() {
|
||||||
|
if (this.invoiceOut)
|
||||||
|
return JSON.stringify({refFk: this.invoiceOut.ref});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
loadData() {
|
loadData() {
|
||||||
const filter = {
|
const filter = {
|
||||||
include: [
|
include: [
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
let UserError = require('vn-loopback/util/user-error');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('createIntrastat', {
|
Self.remoteMethod('createIntrastat', {
|
||||||
description: 'Creates a new item intrastat',
|
description: 'Creates a new item intrastat',
|
||||||
|
|
|
@ -100,34 +100,27 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.filter = async(ctx, filter) => {
|
Self.filter = async(ctx, filter) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
const conn = Self.dataSource.connector;
|
const conn = Self.dataSource.connector;
|
||||||
|
const models = Self.app.models;
|
||||||
const args = ctx.args;
|
const args = ctx.args;
|
||||||
|
|
||||||
let worker = await Self.app.models.Worker.findOne({
|
// Apply filter by team
|
||||||
where: {userFk: ctx.req.accessToken.userId},
|
const teamMembersId = [];
|
||||||
include: [
|
if (args.myTeam != null) {
|
||||||
{relation: 'collegues'}
|
const worker = await models.Worker.findById(userId, {
|
||||||
]
|
include: {
|
||||||
});
|
relation: 'collegues'
|
||||||
|
}
|
||||||
let teamIds = [];
|
|
||||||
|
|
||||||
if (worker.collegues().length && args.myTeam) {
|
|
||||||
worker.collegues().forEach(collegue => {
|
|
||||||
teamIds.push(collegue.collegueFk);
|
|
||||||
});
|
});
|
||||||
}
|
const collegues = worker.collegues() || [];
|
||||||
|
collegues.forEach(collegue => {
|
||||||
if (args.mine || (worker.collegues().length === 0 && args.myTeam)) {
|
teamMembersId.push(collegue.collegueFk);
|
||||||
worker = await Self.app.models.Worker.findOne({
|
|
||||||
fields: ['id'],
|
|
||||||
where: {userFk: ctx.req.accessToken.userId}
|
|
||||||
});
|
});
|
||||||
teamIds = [worker && worker.id];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.args && (args.mine || args.myTeam))
|
if (teamMembersId.length == 0)
|
||||||
args.teamIds = teamIds;
|
teamMembersId.push(userId);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx.args && args.to) {
|
if (ctx.args && args.to) {
|
||||||
const dateTo = args.to;
|
const dateTo = args.to;
|
||||||
|
@ -156,7 +149,11 @@ module.exports = Self => {
|
||||||
return {'ts.stateFk': value};
|
return {'ts.stateFk': value};
|
||||||
case 'mine':
|
case 'mine':
|
||||||
case 'myTeam':
|
case 'myTeam':
|
||||||
return {'c.salesPersonFk': {inq: teamIds}};
|
if (value)
|
||||||
|
return {'c.salesPersonFk': {inq: teamMembersId}};
|
||||||
|
else
|
||||||
|
return {'c.salesPersonFk': {nin: teamMembersId}};
|
||||||
|
|
||||||
case 'alertLevel':
|
case 'alertLevel':
|
||||||
return {'ts.alertLevel': value};
|
return {'ts.alertLevel': value};
|
||||||
case 'pending':
|
case 'pending':
|
||||||
|
@ -186,43 +183,46 @@ module.exports = Self => {
|
||||||
let stmt;
|
let stmt;
|
||||||
|
|
||||||
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.filter');
|
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.filter');
|
||||||
|
|
||||||
stmt = new ParameterizedSQL(
|
stmt = new ParameterizedSQL(
|
||||||
`CREATE TEMPORARY TABLE tmp.filter
|
`CREATE TEMPORARY TABLE tmp.filter
|
||||||
(INDEX (id))
|
(INDEX (id))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT
|
SELECT
|
||||||
t.id,
|
t.id,
|
||||||
t.shipped,
|
t.shipped,
|
||||||
t.nickname,
|
CAST(DATE(t.shipped) AS CHAR) AS shippedDate,
|
||||||
t.refFk,
|
t.nickname,
|
||||||
t.routeFk,
|
t.refFk,
|
||||||
t.warehouseFk,
|
t.routeFk,
|
||||||
t.clientFk,
|
t.warehouseFk,
|
||||||
p.name AS province,
|
t.clientFk,
|
||||||
w.name AS warehouse,
|
a.provinceFk,
|
||||||
am.name AS agencyMode,
|
p.name AS province,
|
||||||
st.name AS state,
|
w.name AS warehouse,
|
||||||
wk.lastName AS salesPerson,
|
am.name AS agencyMode,
|
||||||
ts.stateFk as stateFk,
|
am.id AS agencyModeFk,
|
||||||
ts.alertLevel as alertLevel,
|
st.name AS state,
|
||||||
ts.code as alertLevelCode,
|
wk.lastName AS salesPerson,
|
||||||
u.nickname userNickname,
|
ts.stateFk as stateFk,
|
||||||
c.salesPersonFk,
|
ts.alertLevel as alertLevel,
|
||||||
z.hour zoneLanding,
|
ts.code as alertLevelCode,
|
||||||
HOUR(z.hour) zoneHour,
|
u.nickname userNickname,
|
||||||
MINUTE(z.hour) zoneMinute
|
c.salesPersonFk,
|
||||||
FROM ticket t
|
z.hour zoneLanding,
|
||||||
LEFT JOIN zone z ON z.id = t.zoneFk
|
HOUR(z.hour) zoneHour,
|
||||||
LEFT JOIN address a ON a.id = t.addressFk
|
MINUTE(z.hour) zoneMinute,
|
||||||
LEFT JOIN province p ON p.id = a.provinceFk
|
CAST(z.hour AS CHAR) AS hour
|
||||||
LEFT JOIN warehouse w ON w.id = t.warehouseFk
|
FROM ticket t
|
||||||
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
LEFT JOIN zone z ON z.id = t.zoneFk
|
||||||
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
|
LEFT JOIN address a ON a.id = t.addressFk
|
||||||
LEFT JOIN state st ON st.id = ts.stateFk
|
LEFT JOIN province p ON p.id = a.provinceFk
|
||||||
LEFT JOIN client c ON c.id = t.clientFk
|
LEFT JOIN warehouse w ON w.id = t.warehouseFk
|
||||||
LEFT JOIN worker wk ON wk.id = c.salesPersonFk
|
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||||
LEFT JOIN account.user u ON u.id = wk.userFk`);
|
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
|
||||||
|
LEFT JOIN state st ON st.id = ts.stateFk
|
||||||
|
LEFT JOIN client c ON c.id = t.clientFk
|
||||||
|
LEFT JOIN worker wk ON wk.id = c.salesPersonFk
|
||||||
|
LEFT JOIN account.user u ON u.id = wk.userFk`);
|
||||||
|
|
||||||
if (args.orderFk) {
|
if (args.orderFk) {
|
||||||
stmt.merge({
|
stmt.merge({
|
||||||
|
|
|
@ -105,7 +105,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
if (shipped && !landed) {
|
if (shipped && !landed) {
|
||||||
const landedResult = await models.Agency.getLanded(shipped,
|
const landedResult = await models.Agency.getLanded(shipped,
|
||||||
address.id, agencyModeId, warehouseId);
|
address.id, agencyModeId, warehouseId, false);
|
||||||
landed = landedResult && landedResult.landed;
|
landed = landedResult && landedResult.landed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,18 +43,6 @@ module.exports = Self => {
|
||||||
if (hasItemShelvingSales && !isSalesAssistant)
|
if (hasItemShelvingSales && !isSalesAssistant)
|
||||||
throw new UserError(`You cannot delete a ticket that part of it is being prepared`);
|
throw new UserError(`You cannot delete a ticket that part of it is being prepared`);
|
||||||
|
|
||||||
if (hasItemShelvingSales && isSalesAssistant) {
|
|
||||||
const promises = [];
|
|
||||||
for (let sale of sales) {
|
|
||||||
if (sale.itemShelvingSale()) {
|
|
||||||
const itemShelvingSale = sale.itemShelvingSale();
|
|
||||||
const destroyedShelving = models.ItemShelvingSale.destroyById(itemShelvingSale.id);
|
|
||||||
promises.push(destroyedShelving);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await Promise.all(promises);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for existing claim
|
// Check for existing claim
|
||||||
const claimOfATicket = await models.Claim.findOne({where: {ticketFk: id}});
|
const claimOfATicket = await models.Claim.findOne({where: {ticketFk: id}});
|
||||||
if (claimOfATicket)
|
if (claimOfATicket)
|
||||||
|
@ -69,10 +57,23 @@ module.exports = Self => {
|
||||||
if (hasPurchaseRequests)
|
if (hasPurchaseRequests)
|
||||||
throw new UserError('You must delete all the buy requests first');
|
throw new UserError('You must delete all the buy requests first');
|
||||||
|
|
||||||
|
// removes item shelvings
|
||||||
|
if (hasItemShelvingSales && isSalesAssistant) {
|
||||||
|
const promises = [];
|
||||||
|
for (let sale of sales) {
|
||||||
|
if (sale.itemShelvingSale()) {
|
||||||
|
const itemShelvingSale = sale.itemShelvingSale();
|
||||||
|
const destroyedShelving = models.ItemShelvingSale.destroyById(itemShelvingSale.id);
|
||||||
|
promises.push(destroyedShelving);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove ticket greuges
|
// Remove ticket greuges
|
||||||
const ticketGreuges = await models.Greuge.find({where: {ticketFk: id}});
|
const ticketGreuges = await models.Greuge.find({where: {ticketFk: id}});
|
||||||
const ownGreuges = ticketGreuges.every(greuge => {
|
const ownGreuges = ticketGreuges.every(greuge => {
|
||||||
return greuge.ticketFk = id;
|
return greuge.ticketFk == id;
|
||||||
});
|
});
|
||||||
if (ownGreuges) {
|
if (ownGreuges) {
|
||||||
for (const greuge of ticketGreuges) {
|
for (const greuge of ticketGreuges) {
|
||||||
|
@ -104,7 +105,7 @@ module.exports = Self => {
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
// Change state to "fixing" if contains an stowaway
|
// Change state to "fixing" if contains an stowaway and removed the link between them
|
||||||
let otherTicketId;
|
let otherTicketId;
|
||||||
if (ticket.stowaway())
|
if (ticket.stowaway())
|
||||||
otherTicketId = ticket.stowaway().shipFk;
|
otherTicketId = ticket.stowaway().shipFk;
|
||||||
|
@ -112,6 +113,7 @@ module.exports = Self => {
|
||||||
otherTicketId = ticket.ship().id;
|
otherTicketId = ticket.ship().id;
|
||||||
|
|
||||||
if (otherTicketId) {
|
if (otherTicketId) {
|
||||||
|
await models.Ticket.deleteStowaway(ctx, otherTicketId);
|
||||||
await models.TicketTracking.changeState(ctx, {
|
await models.TicketTracking.changeState(ctx, {
|
||||||
ticketFk: otherTicketId,
|
ticketFk: otherTicketId,
|
||||||
code: 'FIXING'
|
code: 'FIXING'
|
||||||
|
|
|
@ -71,4 +71,20 @@ describe('ticket filter()', () => {
|
||||||
expect(secondRow.state).toEqual('Entregado');
|
expect(secondRow.state).toEqual('Entregado');
|
||||||
expect(thirdRow.state).toEqual('Entregado');
|
expect(thirdRow.state).toEqual('Entregado');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return the tickets from the worker team', async() => {
|
||||||
|
const ctx = {req: {accessToken: {userId: 9}}, args: {myTeam: true}};
|
||||||
|
const filter = {};
|
||||||
|
const result = await app.models.Ticket.filter(ctx, filter);
|
||||||
|
|
||||||
|
expect(result.length).toEqual(17);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the tickets that are not from the worker team', async() => {
|
||||||
|
const ctx = {req: {accessToken: {userId: 9}}, args: {myTeam: false}};
|
||||||
|
const filter = {};
|
||||||
|
const result = await app.models.Ticket.filter(ctx, filter);
|
||||||
|
|
||||||
|
expect(result.length).toEqual(7);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
let UserError = require('vn-loopback/util/user-error');
|
let UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
|
||||||
describe('ticket new()', () => {
|
describe('ticket new()', () => {
|
||||||
let ticket;
|
let ticket;
|
||||||
let today = new Date();
|
let today = new Date();
|
||||||
|
@ -69,7 +68,7 @@ describe('ticket new()', () => {
|
||||||
clientId: 104,
|
clientId: 104,
|
||||||
shipped: today,
|
shipped: today,
|
||||||
landed: today,
|
landed: today,
|
||||||
warehouseId: 1,
|
warehouseId: 2,
|
||||||
companyId: 442,
|
companyId: 442,
|
||||||
addressId: 4,
|
addressId: 4,
|
||||||
agencyModeId: 1
|
agencyModeId: 1
|
||||||
|
|
|
@ -1,116 +1,7 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
const models = app.models;
|
const models = app.models;
|
||||||
|
|
||||||
// 2296 Failing tests
|
describe('ticket setDeleted()', () => {
|
||||||
xdescribe('ticket deleted()', () => {
|
|
||||||
let ticket;
|
|
||||||
let sale;
|
|
||||||
let deletedClaim;
|
|
||||||
|
|
||||||
beforeAll(async done => {
|
|
||||||
let originalTicket = await models.Ticket.findOne({where: {id: 16}});
|
|
||||||
originalTicket.id = null;
|
|
||||||
ticket = await models.Ticket.create(originalTicket);
|
|
||||||
sale = await models.Sale.create({
|
|
||||||
ticketFk: ticket.id,
|
|
||||||
itemFk: 4,
|
|
||||||
concept: 'Melee weapon',
|
|
||||||
quantity: 10
|
|
||||||
});
|
|
||||||
|
|
||||||
await models.ItemShelvingSale.create({
|
|
||||||
itemShelvingFk: 1,
|
|
||||||
saleFk: sale.id,
|
|
||||||
quantity: 10,
|
|
||||||
userFk: 106
|
|
||||||
});
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async done => {
|
|
||||||
const ticketId = 16;
|
|
||||||
const stowawayTicketId = 17;
|
|
||||||
const ctx = {
|
|
||||||
req: {
|
|
||||||
accessToken: {userId: 106},
|
|
||||||
headers: {
|
|
||||||
origin: 'http://localhost:5000'
|
|
||||||
},
|
|
||||||
__: () => {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await models.Ticket.destroyById(ticket.id);
|
|
||||||
const stowaway = await models.Stowaway.findOne({
|
|
||||||
where: {
|
|
||||||
id: stowawayTicketId,
|
|
||||||
shipFk: ticketId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await stowaway.destroy();
|
|
||||||
await models.Claim.create(deletedClaim);
|
|
||||||
await models.TicketTracking.changeState(ctx, {
|
|
||||||
ticketFk: ticketId,
|
|
||||||
code: 'OK'
|
|
||||||
});
|
|
||||||
await models.TicketTracking.changeState(ctx, {
|
|
||||||
ticketFk: stowawayTicketId,
|
|
||||||
code: 'OK'
|
|
||||||
});
|
|
||||||
const orgTicket = await models.Ticket.findById(ticketId);
|
|
||||||
await orgTicket.updateAttribute('isDeleted', false);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make sure the ticket is not deleted yet', async() => {
|
|
||||||
expect(ticket.isDeleted).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make sure the ticket sale has an item shelving', async() => {
|
|
||||||
const sales = await models.Sale.find({
|
|
||||||
include: {relation: 'itemShelvingSale'},
|
|
||||||
where: {ticketFk: ticket.id}
|
|
||||||
});
|
|
||||||
const hasItemShelvingSales = sales.some(sale => {
|
|
||||||
return sale.itemShelvingSale();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(hasItemShelvingSales).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set a ticket to deleted and remove all item shelvings', async() => {
|
|
||||||
const salesAssistantId = 21;
|
|
||||||
const ctx = {
|
|
||||||
req: {
|
|
||||||
accessToken: {userId: salesAssistantId},
|
|
||||||
headers: {
|
|
||||||
origin: 'http://localhost:5000'
|
|
||||||
},
|
|
||||||
__: () => {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await app.models.Ticket.setDeleted(ctx, ticket.id);
|
|
||||||
|
|
||||||
let deletedTicket = await app.models.Ticket.findOne({
|
|
||||||
where: {id: ticket.id},
|
|
||||||
fields: ['isDeleted']
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(deletedTicket.isDeleted).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not have any item shelving', async() => {
|
|
||||||
const sales = await models.Sale.find({
|
|
||||||
include: {relation: 'itemShelvingSale'},
|
|
||||||
where: {ticketFk: ticket.id}
|
|
||||||
});
|
|
||||||
const hasItemShelvingSales = sales.some(sale => {
|
|
||||||
return sale.itemShelvingSale();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(hasItemShelvingSales).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if the given ticket has a claim', async() => {
|
it('should throw an error if the given ticket has a claim', async() => {
|
||||||
const ticketId = 16;
|
const ticketId = 16;
|
||||||
const ctx = {
|
const ctx = {
|
||||||
|
@ -134,13 +25,11 @@ xdescribe('ticket deleted()', () => {
|
||||||
expect(error.message).toEqual('You must delete the claim id %d first');
|
expect(error.message).toEqual('You must delete the claim id %d first');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete the ticket and change the state to "FIXING" to the stowaway ticket', async() => {
|
it('should delete the ticket, remove the stowaway link and change the stowaway ticket state to "FIXING" and get ride of the itemshelving', async() => {
|
||||||
const ticketId = 16;
|
const employeeUser = 110;
|
||||||
const claimIdToRemove = 2;
|
|
||||||
const stowawayTicketId = 17;
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
req: {
|
req: {
|
||||||
accessToken: {userId: 106},
|
accessToken: {userId: employeeUser},
|
||||||
headers: {
|
headers: {
|
||||||
origin: 'http://localhost:5000'
|
origin: 'http://localhost:5000'
|
||||||
},
|
},
|
||||||
|
@ -148,20 +37,66 @@ xdescribe('ticket deleted()', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
await app.models.Stowaway.rawSql(`
|
let sampleTicket = await models.Ticket.findById(12);
|
||||||
INSERT INTO vn.stowaway(id, shipFk)
|
let sampleStowaway = await models.Ticket.findById(13);
|
||||||
VALUES (?, ?)`, [stowawayTicketId, ticketId]);
|
|
||||||
|
|
||||||
deletedClaim = await app.models.Claim.findById(claimIdToRemove);
|
sampleTicket.id = undefined;
|
||||||
await app.models.Claim.destroyById(claimIdToRemove);
|
let shipTicket = await models.Ticket.create(sampleTicket);
|
||||||
await app.models.Ticket.setDeleted(ctx, ticketId);
|
|
||||||
|
|
||||||
const stowawayTicket = await app.models.TicketState.findOne({
|
sampleStowaway.id = undefined;
|
||||||
|
let stowawayTicket = await models.Ticket.create(sampleStowaway);
|
||||||
|
|
||||||
|
await models.Stowaway.rawSql(`
|
||||||
|
INSERT INTO vn.stowaway(id, shipFk)
|
||||||
|
VALUES (?, ?)`, [stowawayTicket.id, shipTicket.id]);
|
||||||
|
|
||||||
|
const boardingState = await models.State.findOne({
|
||||||
where: {
|
where: {
|
||||||
ticketFk: stowawayTicketId
|
code: 'BOARDING'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await models.TicketTracking.create({
|
||||||
|
ticketFk: stowawayTicket.id,
|
||||||
|
stateFk: boardingState.id,
|
||||||
|
workerFk: ctx.req.accessToken.userId
|
||||||
|
});
|
||||||
|
|
||||||
|
const okState = await models.State.findOne({
|
||||||
|
where: {
|
||||||
|
code: 'OK'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await models.TicketTracking.create({
|
||||||
|
ticketFk: shipTicket.id,
|
||||||
|
stateFk: okState.id,
|
||||||
|
workerFk: ctx.req.accessToken.userId
|
||||||
|
});
|
||||||
|
|
||||||
|
let stowawayTicketState = await models.TicketState.findOne({
|
||||||
|
where: {
|
||||||
|
ticketFk: stowawayTicket.id
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(stowawayTicket.code).toEqual('FIXING');
|
let stowaway = await models.Stowaway.findById(shipTicket.id);
|
||||||
|
|
||||||
|
expect(stowaway).toBeDefined();
|
||||||
|
expect(stowawayTicketState.code).toEqual('BOARDING');
|
||||||
|
|
||||||
|
await models.Ticket.setDeleted(ctx, shipTicket.id);
|
||||||
|
|
||||||
|
stowawayTicketState = await models.TicketState.findOne({
|
||||||
|
where: {
|
||||||
|
ticketFk: stowawayTicket.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stowaway = await models.Stowaway.findById(shipTicket.id);
|
||||||
|
|
||||||
|
expect(stowaway).toBeNull();
|
||||||
|
expect(stowawayTicketState.code).toEqual('FIXING');
|
||||||
|
|
||||||
|
await shipTicket.destroy();
|
||||||
|
await stowawayTicket.destroy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -75,7 +75,8 @@ class Controller extends Component {
|
||||||
shipped: value,
|
shipped: value,
|
||||||
addressFk: this.ticket.addressFk,
|
addressFk: this.ticket.addressFk,
|
||||||
agencyModeFk: this.ticket.agencyModeFk,
|
agencyModeFk: this.ticket.agencyModeFk,
|
||||||
warehouseFk: this.ticket.warehouseFk
|
warehouseFk: this.ticket.warehouseFk,
|
||||||
|
showExpiredZones: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +105,8 @@ class Controller extends Component {
|
||||||
shipped: this.ticket.shipped,
|
shipped: this.ticket.shipped,
|
||||||
addressFk: this.ticket.addressFk,
|
addressFk: this.ticket.addressFk,
|
||||||
agencyModeFk: value,
|
agencyModeFk: value,
|
||||||
warehouseFk: this.ticket.warehouseFk
|
warehouseFk: this.ticket.warehouseFk,
|
||||||
|
showExpiredZones: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,13 @@ import './index.js';
|
||||||
|
|
||||||
describe('Ticket', () => {
|
describe('Ticket', () => {
|
||||||
describe('Component vnTicketBasicDataStepOne', () => {
|
describe('Component vnTicketBasicDataStepOne', () => {
|
||||||
let $state;
|
|
||||||
let controller;
|
let controller;
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
let $httpParamSerializer;
|
let $httpParamSerializer;
|
||||||
|
|
||||||
beforeEach(ngModule('ticket'));
|
beforeEach(ngModule('ticket'));
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(($componentController, _$state_, _$httpBackend_, _$httpParamSerializer_) => {
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
||||||
$state = _$state_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
$httpParamSerializer = _$httpParamSerializer_;
|
||||||
const $element = angular.element('<vn-ticket-basic-data-step-one></vn-ticket-basic-data-step-one>');
|
const $element = angular.element('<vn-ticket-basic-data-step-one></vn-ticket-basic-data-step-one>');
|
||||||
|
@ -127,6 +125,7 @@ describe('Ticket', () => {
|
||||||
shipped: shipped,
|
shipped: shipped,
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: 7,
|
agencyModeFk: 7,
|
||||||
|
showExpiredZones: false,
|
||||||
warehouseFk: 1
|
warehouseFk: 1
|
||||||
};
|
};
|
||||||
controller.shipped = shipped;
|
controller.shipped = shipped;
|
||||||
|
@ -177,7 +176,8 @@ describe('Ticket', () => {
|
||||||
shipped: shipped,
|
shipped: shipped,
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: agencyModeId,
|
agencyModeFk: agencyModeId,
|
||||||
warehouseFk: 1
|
warehouseFk: 1,
|
||||||
|
showExpiredZones: false,
|
||||||
};
|
};
|
||||||
controller.ticket.shipped = shipped;
|
controller.ticket.shipped = shipped;
|
||||||
controller.agencyModeId = 8;
|
controller.agencyModeId = 8;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
data="ticketUpdateActions"
|
data="ticketUpdateActions"
|
||||||
auto-load="true">
|
auto-load="true">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-card class="vn-w-lg vn-pa-md vn-mb-md">
|
<vn-card ng-show="::$ctrl.totalPriceDifference" class="vn-w-lg vn-pa-md vn-mb-md">
|
||||||
<h6
|
<h6
|
||||||
class="text-secondary"
|
class="text-secondary"
|
||||||
style="font-weight: normal;"
|
style="font-weight: normal;"
|
||||||
|
|
|
@ -15,16 +15,16 @@
|
||||||
</vn-th>
|
</vn-th>
|
||||||
<vn-th></vn-th>
|
<vn-th></vn-th>
|
||||||
<vn-th field="id" number>Id</vn-th>
|
<vn-th field="id" number>Id</vn-th>
|
||||||
<vn-th field="salesPerson" class="expendable">Salesperson</vn-th>
|
<vn-th field="salesPersonFk" class="expendable">Salesperson</vn-th>
|
||||||
<vn-th field="shipped">Date</vn-th>
|
<vn-th field="shipped">Date</vn-th>
|
||||||
<vn-th>Hour</vn-th>
|
<vn-th>Hour</vn-th>
|
||||||
<vn-th field="nickname">Alias</vn-th>
|
<vn-th field="nickname">Alias</vn-th>
|
||||||
<vn-th field="province" class="expendable">Province</vn-th>
|
<vn-th field="provinceFk" class="expendable">Province</vn-th>
|
||||||
<vn-th field="state" >State</vn-th>
|
<vn-th field="stateFk" >State</vn-th>
|
||||||
<vn-th field="agencyMode">Agency</vn-th>
|
<vn-th field="agencyModeFk">Agency</vn-th>
|
||||||
<vn-th field="warehouse">Warehouse</vn-th>
|
<vn-th field="warehouseFk">Warehouse</vn-th>
|
||||||
<vn-th field="refFk" class="expendable">Invoice</vn-th>
|
<vn-th field="refFk" class="expendable">Invoice</vn-th>
|
||||||
<vn-th field="zoneHour" shrink>Closure</vn-th>
|
<vn-th field="hour" shrink>Closure</vn-th>
|
||||||
<vn-th number>Total</vn-th>
|
<vn-th number>Total</vn-th>
|
||||||
<vn-th></vn-th>
|
<vn-th></vn-th>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
|
@ -151,3 +151,27 @@
|
||||||
<vn-client-balance-create
|
<vn-client-balance-create
|
||||||
vn-id="balanceCreateDialog">
|
vn-id="balanceCreateDialog">
|
||||||
</vn-client-balance-create>
|
</vn-client-balance-create>
|
||||||
|
<vn-contextmenu vn-id="contextmenu" targets="['vn-data-viewer']" model="model"
|
||||||
|
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||||
|
<slot-menu>
|
||||||
|
<vn-item translate
|
||||||
|
ng-if="contextmenu.isFilterAllowed()"
|
||||||
|
ng-click="contextmenu.filterBySelection()">
|
||||||
|
Filter by selection
|
||||||
|
</vn-item>
|
||||||
|
<vn-item translate
|
||||||
|
ng-if="contextmenu.isFilterAllowed()"
|
||||||
|
ng-click="contextmenu.excludeSelection()">
|
||||||
|
Exclude selection
|
||||||
|
</vn-item>
|
||||||
|
<vn-item translate
|
||||||
|
ng-if="contextmenu.isFilterAllowed()"
|
||||||
|
ng-click="contextmenu.removeFilter()" >
|
||||||
|
Remove filter
|
||||||
|
</vn-item>
|
||||||
|
<vn-item translate
|
||||||
|
ng-click="contextmenu.removeAllFilters()" >
|
||||||
|
Remove all filters
|
||||||
|
</vn-item>
|
||||||
|
</slot-menu>
|
||||||
|
</vn-contextmenu>
|
|
@ -92,6 +92,38 @@ export default class Controller extends Section {
|
||||||
this.selectedTicket = ticket;
|
this.selectedTicket = ticket;
|
||||||
this.$.summary.show();
|
this.$.summary.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exprBuilder(param, value) {
|
||||||
|
switch (param) {
|
||||||
|
case 'stateFk':
|
||||||
|
return {'ts.stateFk': value};
|
||||||
|
case 'salesPersonFk':
|
||||||
|
return {'c.salesPersonFk': value};
|
||||||
|
case 'provinceFk':
|
||||||
|
return {'a.provinceFk': value};
|
||||||
|
case 'hour':
|
||||||
|
return {'z.hour': value};
|
||||||
|
case 'shipped':
|
||||||
|
return {'t.shipped': {
|
||||||
|
between: this.dateRange(value)}
|
||||||
|
};
|
||||||
|
case 'id':
|
||||||
|
case 'refFk':
|
||||||
|
case 'nickname':
|
||||||
|
case 'agencyModeFk':
|
||||||
|
case 'warehouseFk':
|
||||||
|
return {[`t.${param}`]: value};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dateRange(value) {
|
||||||
|
const minHour = new Date(value);
|
||||||
|
minHour.setHours(0, 0, 0, 0);
|
||||||
|
const maxHour = new Date(value);
|
||||||
|
maxHour.setHours(23, 59, 59, 59);
|
||||||
|
|
||||||
|
return [minHour, maxHour];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.component('vnTicketIndex', {
|
ngModule.component('vnTicketIndex', {
|
||||||
|
|
|
@ -3,4 +3,8 @@ Go to lines: Ir a lineas
|
||||||
Not available: No disponible
|
Not available: No disponible
|
||||||
Payment on account...: Pago a cuenta...
|
Payment on account...: Pago a cuenta...
|
||||||
Closure: Cierre
|
Closure: Cierre
|
||||||
You cannot make a payment on account from multiple clients: No puedes realizar un pago a cuenta de clientes diferentes
|
You cannot make a payment on account from multiple clients: No puedes realizar un pago a cuenta de clientes diferentes
|
||||||
|
Filter by selection: Filtro por selección
|
||||||
|
Exclude selection: Excluir selección
|
||||||
|
Remove filter: Quitar filtro por selección
|
||||||
|
Remove all filters: Eliminar todos los filtros
|
|
@ -17,6 +17,20 @@ class Controller extends Section {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
showDescriptor(event, sale) {
|
||||||
|
this.quicklinks = {
|
||||||
|
btnThree: {
|
||||||
|
icon: 'icon-transaction',
|
||||||
|
state: `item.card.diary({
|
||||||
|
id: ${sale.itemFk},
|
||||||
|
warehouseFk: ${this.ticket.warehouseFk},
|
||||||
|
lineFk: ${sale.id}
|
||||||
|
})`,
|
||||||
|
tooltip: 'Item diary'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.$.descriptor.show(event.target, sale.itemFk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.component('vnTicketSaleChecked', {
|
ngModule.component('vnTicketSaleChecked', {
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
<div class="attributes">
|
<div class="attributes">
|
||||||
<vn-label-value
|
<vn-label-value
|
||||||
label="Wh. In"
|
label="Wh. In"
|
||||||
value="{{$ctrl.travel.warehouseOut.name}}">
|
value="{{$ctrl.travel.warehouseIn.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value
|
<vn-label-value
|
||||||
label="Wh. Out"
|
label="Wh. Out"
|
||||||
value="{{$ctrl.travel.warehouseIn.name}}">
|
value="{{$ctrl.travel.warehouseOut.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value
|
<vn-label-value
|
||||||
label="Shipped"
|
label="Shipped"
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<span translate class="label">Changed by</span><span class="label">: </span>
|
<span translate class="label">Changed by</span><span class="label">: </span>
|
||||||
<span
|
<span
|
||||||
ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
|
ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
|
||||||
ng-click="workerDescriptor.show($event, log.user.id)"
|
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
|
||||||
translate>{{::log.user.name | dashIfEmpty}}
|
translate>{{::log.user.name | dashIfEmpty}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
<vn-td class="expendable">
|
<vn-td class="expendable">
|
||||||
<span
|
<span
|
||||||
ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
|
ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
|
||||||
ng-click="workerDescriptor.show($event, log.user.id)"
|
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
|
||||||
translate>{{::log.user.name | dashIfEmpty}}
|
translate>{{::log.user.name | dashIfEmpty}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
|
|
|
@ -57,6 +57,11 @@ export default class Controller extends Section {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showWorkerDescriptor(event, workerId) {
|
||||||
|
if (!workerId) return;
|
||||||
|
this.$.workerDescriptor.show(event.target, workerId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.component('vnLog', {
|
ngModule.component('vnLog', {
|
||||||
|
|
|
@ -23,6 +23,11 @@ module.exports = Self => {
|
||||||
arg: 'warehouseFk',
|
arg: 'warehouseFk',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'showExpiredZones',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
@ -34,14 +39,15 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getLanded = async(shipped, addressFk, agencyModeFk, warehouseFk) => {
|
Self.getLanded = async(shipped, addressFk, agencyModeFk, warehouseFk, showExpiredZones) => {
|
||||||
let stmts = [];
|
let stmts = [];
|
||||||
stmts.push(new ParameterizedSQL(
|
stmts.push(new ParameterizedSQL(
|
||||||
`CALL vn.zone_getLanded(?, ?, ?, ?)`, [
|
`CALL vn.zone_getLanded(?, ?, ?, ?, ?)`, [
|
||||||
shipped,
|
shipped,
|
||||||
addressFk,
|
addressFk,
|
||||||
agencyModeFk,
|
agencyModeFk,
|
||||||
warehouseFk
|
warehouseFk,
|
||||||
|
showExpiredZones
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ describe('agency getLanded()', () => {
|
||||||
const addressFk = 121;
|
const addressFk = 121;
|
||||||
const agencyModeFk = 7;
|
const agencyModeFk = 7;
|
||||||
const warehouseFk = 1;
|
const warehouseFk = 1;
|
||||||
let result = await app.models.Agency.getLanded(shipped, addressFk, agencyModeFk, warehouseFk);
|
const showExpiredZones = true;
|
||||||
|
let result = await app.models.Agency.getLanded(shipped, addressFk, agencyModeFk, warehouseFk, showExpiredZones);
|
||||||
|
|
||||||
expect(result.landed).toBeDefined();
|
expect(result.landed).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
// 2302
|
||||||
describe('zone deletezone()', () => {
|
describe('zone deletezone()', () => {
|
||||||
let zoneId = 1;
|
let zoneId = 9;
|
||||||
let originalZoneTickets;
|
let originalZoneTickets;
|
||||||
let originalZone;
|
let originalZone;
|
||||||
|
let originalZoneIncluded;
|
||||||
|
|
||||||
beforeAll(async done => {
|
beforeAll(async done => {
|
||||||
originalZone = await app.models.Zone.findById(zoneId);
|
originalZone = await app.models.Zone.findById(zoneId);
|
||||||
originalZoneTickets = await app.models.Ticket.find({where: {zoneFk: zoneId}});
|
originalZoneTickets = await app.models.Ticket.find({where: {zoneFk: zoneId}});
|
||||||
|
originalZoneIncluded = await app.models.ZoneIncluded.find({where: {zoneFk: zoneId}});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,6 +20,9 @@ describe('zone deletezone()', () => {
|
||||||
originalZoneTickets.forEach(async ticket => {
|
originalZoneTickets.forEach(async ticket => {
|
||||||
await ticket.updateAttributes({zoneFk: zoneId});
|
await ticket.updateAttributes({zoneFk: zoneId});
|
||||||
});
|
});
|
||||||
|
originalZoneIncluded.forEach(async zoneIncluded => {
|
||||||
|
await zoneIncluded.save();
|
||||||
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
|
@ -56,9 +56,9 @@
|
||||||
"gulp-install": "^1.1.0",
|
"gulp-install": "^1.1.0",
|
||||||
"gulp-jasmine": "^4.0.0",
|
"gulp-jasmine": "^4.0.0",
|
||||||
"gulp-merge-json": "^1.3.1",
|
"gulp-merge-json": "^1.3.1",
|
||||||
"gulp-nodemon": "^2.4.2",
|
"gulp-nodemon": "^2.5.0",
|
||||||
"gulp-print": "^2.0.1",
|
"gulp-print": "^2.0.1",
|
||||||
"gulp-wrap": "^0.13.0",
|
"gulp-wrap": "^0.15.0",
|
||||||
"gulp-yaml": "^1.0.1",
|
"gulp-yaml": "^1.0.1",
|
||||||
"html-loader": "^0.4.5",
|
"html-loader": "^0.4.5",
|
||||||
"html-loader-jest": "^0.2.1",
|
"html-loader-jest": "^0.2.1",
|
||||||
|
@ -71,9 +71,9 @@
|
||||||
"jest-junit": "^8.0.0",
|
"jest-junit": "^8.0.0",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"merge-stream": "^1.0.1",
|
"merge-stream": "^1.0.1",
|
||||||
"minimist": "^1.2.0",
|
"minimist": "^1.2.5",
|
||||||
"mysql2": "^1.7.0",
|
"mysql2": "^1.7.0",
|
||||||
"node-sass": "^4.13.0",
|
"node-sass": "^4.14.1",
|
||||||
"nodemon": "^1.19.4",
|
"nodemon": "^1.19.4",
|
||||||
"plugin-error": "^1.0.1",
|
"plugin-error": "^1.0.1",
|
||||||
"puppeteer": "^2.0.0",
|
"puppeteer": "^2.0.0",
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
"style-loader": "^0.23.1",
|
"style-loader": "^0.23.1",
|
||||||
"webpack": "^4.41.5",
|
"webpack": "^4.41.5",
|
||||||
"webpack-cli": "^3.3.10",
|
"webpack-cli": "^3.3.10",
|
||||||
"webpack-dev-server": "^3.10.1",
|
"webpack-dev-server": "^3.11.0",
|
||||||
"webpack-merge": "^4.2.2",
|
"webpack-merge": "^4.2.2",
|
||||||
"yaml-loader": "^0.5.0"
|
"yaml-loader": "^0.5.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,9 +72,10 @@ class Email extends Component {
|
||||||
await getAttachments(this.path, this.attachments);
|
await getAttachments(this.path, this.attachments);
|
||||||
|
|
||||||
const localeSubject = await this.getSubject();
|
const localeSubject = await this.getSubject();
|
||||||
|
const replyTo = this.args.replyTo || this.args.auth.email;
|
||||||
const options = {
|
const options = {
|
||||||
to: this.args.recipient,
|
to: this.args.recipient,
|
||||||
replyTo: this.args.auth.email,
|
replyTo: replyTo,
|
||||||
subject: localeSubject,
|
subject: localeSubject,
|
||||||
html: rendered,
|
html: rendered,
|
||||||
attachments: attachments
|
attachments: attachments
|
||||||
|
|
|
@ -58,7 +58,8 @@ module.exports = app => {
|
||||||
const args = Object.assign({
|
const args = Object.assign({
|
||||||
ticketId: ticket.id,
|
ticketId: ticket.id,
|
||||||
recipientId: ticket.clientFk,
|
recipientId: ticket.clientFk,
|
||||||
recipient: ticket.recipient
|
recipient: ticket.recipient,
|
||||||
|
replyTo: ticket.salesPersonEmail
|
||||||
}, reqArgs);
|
}, reqArgs);
|
||||||
|
|
||||||
const email = new Email('delivery-note-link', args);
|
const email = new Email('delivery-note-link', args);
|
||||||
|
|
Loading…
Reference in New Issue