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`
|
||||
});
|
||||
|
||||
Self.observe('before save', (ctx, next) => {
|
||||
Self.observe('before save', async function(ctx) {
|
||||
if (ctx.currentInstance && ctx.currentInstance.id && ctx.data && 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', {
|
||||
|
|
|
@ -45,7 +45,7 @@ proc: BEGIN
|
|||
|
||||
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
|
||||
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 = {
|
||||
addressFk: 121,
|
||||
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.agencyModeFk,
|
||||
params.warehouseFk
|
||||
params.warehouseFk,
|
||||
params.showExpiredZones
|
||||
|
||||
]);
|
||||
stmts.push(stmt);
|
||||
|
@ -42,12 +44,14 @@ describe('zone zone_getLanded()', () => {
|
|||
let params = {
|
||||
addressFk: 121,
|
||||
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.agencyModeFk,
|
||||
params.warehouseFk
|
||||
params.warehouseFk,
|
||||
params.showExpiredZones
|
||||
|
||||
]);
|
||||
stmts.push(stmt);
|
||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
|||
ticketsButton: '.modules-menu [ui-sref="ticket.index"]',
|
||||
invoiceOutButton: '.modules-menu [ui-sref="invoiceOut.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',
|
||||
userLocalWarehouse: '.user-popover vn-autocomplete[ng-model="$ctrl.localWarehouseFk"]',
|
||||
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)',
|
||||
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',
|
||||
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: {
|
||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||
|
|
|
@ -4,6 +4,9 @@ import getBrowser from '../../helpers/puppeteer';
|
|||
describe('Ticket create path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
let nextMonth = new Date();
|
||||
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
||||
let stowawayTicketId;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
|
@ -21,13 +24,9 @@ describe('Ticket create path', () => {
|
|||
});
|
||||
|
||||
it('should succeed to create a ticket', async() => {
|
||||
const nextMonth = new Date();
|
||||
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
||||
|
||||
await page.autocompleteSearch(selectors.createTicketView.client, 'Tony Stark');
|
||||
await page.autocompleteSearch(selectors.createTicketView.address, 'Tony Stark');
|
||||
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.warehouse, 'Warehouse Two');
|
||||
await page.autocompleteSearch(selectors.createTicketView.agency, 'Silla247');
|
||||
await page.waitToClick(selectors.createTicketView.createButton);
|
||||
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() => {
|
||||
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>
|
||||
</div>
|
||||
<div class="icons pre">
|
||||
<vn-icon
|
||||
<vn-icon ng-show="::$ctrl.clearDisabled != true"
|
||||
icon="clear"
|
||||
translate-attr="{title: 'Clear'}"
|
||||
ng-click="$ctrl.onClear($event)">
|
||||
|
|
|
@ -203,6 +203,7 @@ ngModule.vnComponent('vnField', {
|
|||
type: '@?',
|
||||
autocomplete: '@?',
|
||||
placeholder: '@?',
|
||||
clearDisabled: '<?',
|
||||
value: '=?',
|
||||
info: '@?',
|
||||
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 './wday-picker';
|
||||
import './datalist';
|
||||
import './contextmenu';
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ngModule from '../../module';
|
||||
import Field from '../field';
|
||||
import './style.scss';
|
||||
|
||||
export default class Textarea extends Field {
|
||||
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, newInstance);
|
||||
|
||||
// Prevent log with no new changes
|
||||
const hasNewChanges = Object.keys(newInstance).length;
|
||||
if (!hasNewChanges) return;
|
||||
|
||||
let logRecord = {
|
||||
originFk: originId,
|
||||
userFk: userFk,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('regularizeClaim()', () => {
|
||||
// #2304
|
||||
xdescribe('regularizeClaim()', () => {
|
||||
const claimFk = 1;
|
||||
const pendentState = 1;
|
||||
const resolvedState = 3;
|
||||
|
|
|
@ -76,8 +76,8 @@
|
|||
<span
|
||||
ng-if="balance.isInvoice"
|
||||
title="{{'BILL' | translate: {ref: balance.ref} }}"
|
||||
vn-click-stop="invoiceOutDescriptor.show($event, balance)"
|
||||
ng-class="link">
|
||||
vn-click-stop="$ctrl.showInvoiceOutDescriptor($event, balance)"
|
||||
class="link">
|
||||
{{'BILL' | translate: {ref: balance.ref} }}
|
||||
</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'];
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<vn-item
|
||||
ng-click="consumerReportDialog.show()"
|
||||
translate>
|
||||
Send consumer report
|
||||
View consumer report
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
<slot-body>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Simple ticket: Ticket simple
|
||||
Send consumer report: Enviar informe de consumo
|
||||
View consumer report: Ver informe de consumo
|
||||
From date: Fecha desde
|
||||
To date: Fecha hasta
|
|
@ -56,7 +56,7 @@
|
|||
<div ng-transclude="btnTwo">
|
||||
<vn-quick-link
|
||||
tooltip="Invoice ticket list"
|
||||
state="['ticket.card.summary', {id: $ctrl.invoiceOut.ref}]"
|
||||
state="['ticket.index', {q: $ctrl.filter}]"
|
||||
icon="icon-ticket">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
|
|
|
@ -22,6 +22,13 @@ class Controller extends Descriptor {
|
|||
.then(() => this.vnApp.showSuccess(this.$t('InvoiceOut booked')));
|
||||
}
|
||||
|
||||
get filter() {
|
||||
if (this.invoiceOut)
|
||||
return JSON.stringify({refFk: this.invoiceOut.ref});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
loadData() {
|
||||
const filter = {
|
||||
include: [
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
let UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('createIntrastat', {
|
||||
description: 'Creates a new item intrastat',
|
||||
|
|
|
@ -100,34 +100,27 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.filter = async(ctx, filter) => {
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
const conn = Self.dataSource.connector;
|
||||
const models = Self.app.models;
|
||||
const args = ctx.args;
|
||||
|
||||
let worker = await Self.app.models.Worker.findOne({
|
||||
where: {userFk: ctx.req.accessToken.userId},
|
||||
include: [
|
||||
{relation: 'collegues'}
|
||||
]
|
||||
});
|
||||
|
||||
let teamIds = [];
|
||||
|
||||
if (worker.collegues().length && args.myTeam) {
|
||||
worker.collegues().forEach(collegue => {
|
||||
teamIds.push(collegue.collegueFk);
|
||||
// Apply filter by team
|
||||
const teamMembersId = [];
|
||||
if (args.myTeam != null) {
|
||||
const worker = await models.Worker.findById(userId, {
|
||||
include: {
|
||||
relation: 'collegues'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (args.mine || (worker.collegues().length === 0 && args.myTeam)) {
|
||||
worker = await Self.app.models.Worker.findOne({
|
||||
fields: ['id'],
|
||||
where: {userFk: ctx.req.accessToken.userId}
|
||||
const collegues = worker.collegues() || [];
|
||||
collegues.forEach(collegue => {
|
||||
teamMembersId.push(collegue.collegueFk);
|
||||
});
|
||||
teamIds = [worker && worker.id];
|
||||
}
|
||||
|
||||
if (ctx.args && (args.mine || args.myTeam))
|
||||
args.teamIds = teamIds;
|
||||
if (teamMembersId.length == 0)
|
||||
teamMembersId.push(userId);
|
||||
}
|
||||
|
||||
if (ctx.args && args.to) {
|
||||
const dateTo = args.to;
|
||||
|
@ -156,7 +149,11 @@ module.exports = Self => {
|
|||
return {'ts.stateFk': value};
|
||||
case 'mine':
|
||||
case 'myTeam':
|
||||
return {'c.salesPersonFk': {inq: teamIds}};
|
||||
if (value)
|
||||
return {'c.salesPersonFk': {inq: teamMembersId}};
|
||||
else
|
||||
return {'c.salesPersonFk': {nin: teamMembersId}};
|
||||
|
||||
case 'alertLevel':
|
||||
return {'ts.alertLevel': value};
|
||||
case 'pending':
|
||||
|
@ -186,43 +183,46 @@ module.exports = Self => {
|
|||
let stmt;
|
||||
|
||||
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.filter');
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`CREATE TEMPORARY TABLE tmp.filter
|
||||
(INDEX (id))
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
t.id,
|
||||
t.shipped,
|
||||
t.nickname,
|
||||
t.refFk,
|
||||
t.routeFk,
|
||||
t.warehouseFk,
|
||||
t.clientFk,
|
||||
p.name AS province,
|
||||
w.name AS warehouse,
|
||||
am.name AS agencyMode,
|
||||
st.name AS state,
|
||||
wk.lastName AS salesPerson,
|
||||
ts.stateFk as stateFk,
|
||||
ts.alertLevel as alertLevel,
|
||||
ts.code as alertLevelCode,
|
||||
u.nickname userNickname,
|
||||
c.salesPersonFk,
|
||||
z.hour zoneLanding,
|
||||
HOUR(z.hour) zoneHour,
|
||||
MINUTE(z.hour) zoneMinute
|
||||
FROM ticket t
|
||||
LEFT JOIN zone z ON z.id = t.zoneFk
|
||||
LEFT JOIN address a ON a.id = t.addressFk
|
||||
LEFT JOIN province p ON p.id = a.provinceFk
|
||||
LEFT JOIN warehouse w ON w.id = t.warehouseFk
|
||||
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||
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`);
|
||||
SELECT
|
||||
t.id,
|
||||
t.shipped,
|
||||
CAST(DATE(t.shipped) AS CHAR) AS shippedDate,
|
||||
t.nickname,
|
||||
t.refFk,
|
||||
t.routeFk,
|
||||
t.warehouseFk,
|
||||
t.clientFk,
|
||||
a.provinceFk,
|
||||
p.name AS province,
|
||||
w.name AS warehouse,
|
||||
am.name AS agencyMode,
|
||||
am.id AS agencyModeFk,
|
||||
st.name AS state,
|
||||
wk.lastName AS salesPerson,
|
||||
ts.stateFk as stateFk,
|
||||
ts.alertLevel as alertLevel,
|
||||
ts.code as alertLevelCode,
|
||||
u.nickname userNickname,
|
||||
c.salesPersonFk,
|
||||
z.hour zoneLanding,
|
||||
HOUR(z.hour) zoneHour,
|
||||
MINUTE(z.hour) zoneMinute,
|
||||
CAST(z.hour AS CHAR) AS hour
|
||||
FROM ticket t
|
||||
LEFT JOIN zone z ON z.id = t.zoneFk
|
||||
LEFT JOIN address a ON a.id = t.addressFk
|
||||
LEFT JOIN province p ON p.id = a.provinceFk
|
||||
LEFT JOIN warehouse w ON w.id = t.warehouseFk
|
||||
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||
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) {
|
||||
stmt.merge({
|
||||
|
|
|
@ -105,7 +105,7 @@ module.exports = Self => {
|
|||
|
||||
if (shipped && !landed) {
|
||||
const landedResult = await models.Agency.getLanded(shipped,
|
||||
address.id, agencyModeId, warehouseId);
|
||||
address.id, agencyModeId, warehouseId, false);
|
||||
landed = landedResult && landedResult.landed;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,18 +43,6 @@ module.exports = Self => {
|
|||
if (hasItemShelvingSales && !isSalesAssistant)
|
||||
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
|
||||
const claimOfATicket = await models.Claim.findOne({where: {ticketFk: id}});
|
||||
if (claimOfATicket)
|
||||
|
@ -69,10 +57,23 @@ module.exports = Self => {
|
|||
if (hasPurchaseRequests)
|
||||
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
|
||||
const ticketGreuges = await models.Greuge.find({where: {ticketFk: id}});
|
||||
const ownGreuges = ticketGreuges.every(greuge => {
|
||||
return greuge.ticketFk = id;
|
||||
return greuge.ticketFk == id;
|
||||
});
|
||||
if (ownGreuges) {
|
||||
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;
|
||||
if (ticket.stowaway())
|
||||
otherTicketId = ticket.stowaway().shipFk;
|
||||
|
@ -112,6 +113,7 @@ module.exports = Self => {
|
|||
otherTicketId = ticket.ship().id;
|
||||
|
||||
if (otherTicketId) {
|
||||
await models.Ticket.deleteStowaway(ctx, otherTicketId);
|
||||
await models.TicketTracking.changeState(ctx, {
|
||||
ticketFk: otherTicketId,
|
||||
code: 'FIXING'
|
||||
|
|
|
@ -71,4 +71,20 @@ describe('ticket filter()', () => {
|
|||
expect(secondRow.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');
|
||||
let UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
|
||||
describe('ticket new()', () => {
|
||||
let ticket;
|
||||
let today = new Date();
|
||||
|
@ -69,7 +68,7 @@ describe('ticket new()', () => {
|
|||
clientId: 104,
|
||||
shipped: today,
|
||||
landed: today,
|
||||
warehouseId: 1,
|
||||
warehouseId: 2,
|
||||
companyId: 442,
|
||||
addressId: 4,
|
||||
agencyModeId: 1
|
||||
|
|
|
@ -1,116 +1,7 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
const models = app.models;
|
||||
|
||||
// 2296 Failing tests
|
||||
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);
|
||||
});
|
||||
|
||||
describe('ticket setDeleted()', () => {
|
||||
it('should throw an error if the given ticket has a claim', async() => {
|
||||
const ticketId = 16;
|
||||
const ctx = {
|
||||
|
@ -134,13 +25,11 @@ xdescribe('ticket deleted()', () => {
|
|||
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() => {
|
||||
const ticketId = 16;
|
||||
const claimIdToRemove = 2;
|
||||
const stowawayTicketId = 17;
|
||||
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 employeeUser = 110;
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 106},
|
||||
accessToken: {userId: employeeUser},
|
||||
headers: {
|
||||
origin: 'http://localhost:5000'
|
||||
},
|
||||
|
@ -148,20 +37,66 @@ xdescribe('ticket deleted()', () => {
|
|||
}
|
||||
};
|
||||
|
||||
await app.models.Stowaway.rawSql(`
|
||||
INSERT INTO vn.stowaway(id, shipFk)
|
||||
VALUES (?, ?)`, [stowawayTicketId, ticketId]);
|
||||
let sampleTicket = await models.Ticket.findById(12);
|
||||
let sampleStowaway = await models.Ticket.findById(13);
|
||||
|
||||
deletedClaim = await app.models.Claim.findById(claimIdToRemove);
|
||||
await app.models.Claim.destroyById(claimIdToRemove);
|
||||
await app.models.Ticket.setDeleted(ctx, ticketId);
|
||||
sampleTicket.id = undefined;
|
||||
let shipTicket = await models.Ticket.create(sampleTicket);
|
||||
|
||||
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: {
|
||||
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,
|
||||
addressFk: this.ticket.addressFk,
|
||||
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,
|
||||
addressFk: this.ticket.addressFk,
|
||||
agencyModeFk: value,
|
||||
warehouseFk: this.ticket.warehouseFk
|
||||
warehouseFk: this.ticket.warehouseFk,
|
||||
showExpiredZones: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,13 @@ import './index.js';
|
|||
|
||||
describe('Ticket', () => {
|
||||
describe('Component vnTicketBasicDataStepOne', () => {
|
||||
let $state;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('ticket'));
|
||||
|
||||
beforeEach(angular.mock.inject(($componentController, _$state_, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$state = _$state_;
|
||||
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
const $element = angular.element('<vn-ticket-basic-data-step-one></vn-ticket-basic-data-step-one>');
|
||||
|
@ -127,6 +125,7 @@ describe('Ticket', () => {
|
|||
shipped: shipped,
|
||||
addressFk: 121,
|
||||
agencyModeFk: 7,
|
||||
showExpiredZones: false,
|
||||
warehouseFk: 1
|
||||
};
|
||||
controller.shipped = shipped;
|
||||
|
@ -177,7 +176,8 @@ describe('Ticket', () => {
|
|||
shipped: shipped,
|
||||
addressFk: 121,
|
||||
agencyModeFk: agencyModeId,
|
||||
warehouseFk: 1
|
||||
warehouseFk: 1,
|
||||
showExpiredZones: false,
|
||||
};
|
||||
controller.ticket.shipped = shipped;
|
||||
controller.agencyModeId = 8;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
data="ticketUpdateActions"
|
||||
auto-load="true">
|
||||
</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
|
||||
class="text-secondary"
|
||||
style="font-weight: normal;"
|
||||
|
|
|
@ -15,16 +15,16 @@
|
|||
</vn-th>
|
||||
<vn-th></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>Hour</vn-th>
|
||||
<vn-th field="nickname">Alias</vn-th>
|
||||
<vn-th field="province" class="expendable">Province</vn-th>
|
||||
<vn-th field="state" >State</vn-th>
|
||||
<vn-th field="agencyMode">Agency</vn-th>
|
||||
<vn-th field="warehouse">Warehouse</vn-th>
|
||||
<vn-th field="provinceFk" class="expendable">Province</vn-th>
|
||||
<vn-th field="stateFk" >State</vn-th>
|
||||
<vn-th field="agencyModeFk">Agency</vn-th>
|
||||
<vn-th field="warehouseFk">Warehouse</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></vn-th>
|
||||
</vn-tr>
|
||||
|
@ -151,3 +151,27 @@
|
|||
<vn-client-balance-create
|
||||
vn-id="balanceCreateDialog">
|
||||
</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.$.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', {
|
||||
|
|
|
@ -4,3 +4,7 @@ Not available: No disponible
|
|||
Payment on account...: Pago a cuenta...
|
||||
Closure: Cierre
|
||||
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', {
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
<div class="attributes">
|
||||
<vn-label-value
|
||||
label="Wh. In"
|
||||
value="{{$ctrl.travel.warehouseOut.name}}">
|
||||
value="{{$ctrl.travel.warehouseIn.name}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Wh. Out"
|
||||
value="{{$ctrl.travel.warehouseIn.name}}">
|
||||
value="{{$ctrl.travel.warehouseOut.name}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Shipped"
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<span translate class="label">Changed by</span><span class="label">: </span>
|
||||
<span
|
||||
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}}
|
||||
</span>
|
||||
</div>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<vn-td class="expendable">
|
||||
<span
|
||||
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}}
|
||||
</span>
|
||||
</vn-td>
|
||||
|
|
|
@ -57,6 +57,11 @@ export default class Controller extends Section {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
showWorkerDescriptor(event, workerId) {
|
||||
if (!workerId) return;
|
||||
this.$.workerDescriptor.show(event.target, workerId);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnLog', {
|
||||
|
|
|
@ -23,6 +23,11 @@ module.exports = Self => {
|
|||
arg: 'warehouseFk',
|
||||
type: 'number',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'showExpiredZones',
|
||||
type: 'boolean',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
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 = [];
|
||||
stmts.push(new ParameterizedSQL(
|
||||
`CALL vn.zone_getLanded(?, ?, ?, ?)`, [
|
||||
`CALL vn.zone_getLanded(?, ?, ?, ?, ?)`, [
|
||||
shipped,
|
||||
addressFk,
|
||||
agencyModeFk,
|
||||
warehouseFk
|
||||
warehouseFk,
|
||||
showExpiredZones
|
||||
]
|
||||
));
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ describe('agency getLanded()', () => {
|
|||
const addressFk = 121;
|
||||
const agencyModeFk = 7;
|
||||
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();
|
||||
});
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
// 2302
|
||||
describe('zone deletezone()', () => {
|
||||
let zoneId = 1;
|
||||
let zoneId = 9;
|
||||
let originalZoneTickets;
|
||||
let originalZone;
|
||||
let originalZoneIncluded;
|
||||
|
||||
beforeAll(async done => {
|
||||
originalZone = await app.models.Zone.findById(zoneId);
|
||||
originalZoneTickets = await app.models.Ticket.find({where: {zoneFk: zoneId}});
|
||||
originalZoneIncluded = await app.models.ZoneIncluded.find({where: {zoneFk: zoneId}});
|
||||
done();
|
||||
});
|
||||
|
||||
|
@ -17,6 +20,9 @@ describe('zone deletezone()', () => {
|
|||
originalZoneTickets.forEach(async ticket => {
|
||||
await ticket.updateAttributes({zoneFk: zoneId});
|
||||
});
|
||||
originalZoneIncluded.forEach(async zoneIncluded => {
|
||||
await zoneIncluded.save();
|
||||
});
|
||||
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-jasmine": "^4.0.0",
|
||||
"gulp-merge-json": "^1.3.1",
|
||||
"gulp-nodemon": "^2.4.2",
|
||||
"gulp-nodemon": "^2.5.0",
|
||||
"gulp-print": "^2.0.1",
|
||||
"gulp-wrap": "^0.13.0",
|
||||
"gulp-wrap": "^0.15.0",
|
||||
"gulp-yaml": "^1.0.1",
|
||||
"html-loader": "^0.4.5",
|
||||
"html-loader-jest": "^0.2.1",
|
||||
|
@ -71,9 +71,9 @@
|
|||
"jest-junit": "^8.0.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"merge-stream": "^1.0.1",
|
||||
"minimist": "^1.2.0",
|
||||
"minimist": "^1.2.5",
|
||||
"mysql2": "^1.7.0",
|
||||
"node-sass": "^4.13.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"nodemon": "^1.19.4",
|
||||
"plugin-error": "^1.0.1",
|
||||
"puppeteer": "^2.0.0",
|
||||
|
@ -82,7 +82,7 @@
|
|||
"style-loader": "^0.23.1",
|
||||
"webpack": "^4.41.5",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack-dev-server": "^3.10.1",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"yaml-loader": "^0.5.0"
|
||||
},
|
||||
|
|
|
@ -72,9 +72,10 @@ class Email extends Component {
|
|||
await getAttachments(this.path, this.attachments);
|
||||
|
||||
const localeSubject = await this.getSubject();
|
||||
const replyTo = this.args.replyTo || this.args.auth.email;
|
||||
const options = {
|
||||
to: this.args.recipient,
|
||||
replyTo: this.args.auth.email,
|
||||
replyTo: replyTo,
|
||||
subject: localeSubject,
|
||||
html: rendered,
|
||||
attachments: attachments
|
||||
|
|
|
@ -58,7 +58,8 @@ module.exports = app => {
|
|||
const args = Object.assign({
|
||||
ticketId: ticket.id,
|
||||
recipientId: ticket.clientFk,
|
||||
recipient: ticket.recipient
|
||||
recipient: ticket.recipient,
|
||||
replyTo: ticket.salesPersonEmail
|
||||
}, reqArgs);
|
||||
|
||||
const email = new Email('delivery-note-link', args);
|
||||
|
|
Loading…
Reference in New Issue