Redirect invoice out to Lilium #2807
|
@ -20,13 +20,14 @@ module.exports = Self => {
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const randStr = Math.random().toString(36).substring(3);
|
||||||
const result = await Self.rawSql(`
|
const result = await Self.rawSql(`
|
||||||
CALL vn.collection_assign(?, @vCollectionFk);
|
CALL vn.collection_assign(?, @vCollectionFk);
|
||||||
SELECT @vCollectionFk collectionFk
|
SELECT @vCollectionFk ?
|
||||||
`, [userId], myOptions);
|
`, [userId, randStr], myOptions);
|
||||||
|
|
||||||
// Por si entra en el SELECT FOR UPDATE y retorna un array más
|
// Por si entra en SELECT FOR UPDATE una o varias veces
|
||||||
const collectionFk = result[2]?.[0]?.collectionFk || result[3]?.[0]?.collectionFk;
|
const collectionFk = result.find(item => item[0]?.[randStr] !== undefined)?.[0]?.[randStr];
|
||||||
|
|
||||||
if (!collectionFk) throw new UserError('There are not picking tickets');
|
if (!collectionFk) throw new UserError('There are not picking tickets');
|
||||||
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);
|
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);
|
||||||
|
|
|
@ -37,7 +37,6 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const xmlString = response.data;
|
const xmlString = response.data;
|
||||||
console.log('xmlString: ', xmlString);
|
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
|
const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
|
||||||
const result = xmlDoc.getElementsByTagName('Mensaje')[0].textContent;
|
const result = xmlDoc.getElementsByTagName('Mensaje')[0].textContent;
|
||||||
|
|
|
@ -47,7 +47,7 @@ module.exports = Self => {
|
||||||
co.code countryCode,
|
co.code countryCode,
|
||||||
c.fi,
|
c.fi,
|
||||||
c.name clientName,
|
c.name clientName,
|
||||||
a.mobile,
|
IFNULL(a.mobile, c.mobile) mobile,
|
||||||
DATE_FORMAT(t.shipped, '%d/%m/%Y') created,
|
DATE_FORMAT(t.shipped, '%d/%m/%Y') created,
|
||||||
t.shipped,
|
t.shipped,
|
||||||
CONCAT( e.ticketFk, LPAD(e.counter, mc.counterWidth, '0')) reference,
|
CONCAT( e.ticketFk, LPAD(e.counter, mc.counterWidth, '0')) reference,
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
"Company": {
|
"Company": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"Config": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Continent": {
|
"Continent": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "Config",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "config"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"inventoried": {
|
||||||
|
"type": "date"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"accessType": "READ",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "$authenticated",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT `vn`.`travel_setDelivered`
|
||||||
|
ON SCHEDULE EVERY 1 DAY
|
||||||
|
STARTS '2024-07-12 00:10:00.000'
|
||||||
|
ON COMPLETION PRESERVE
|
||||||
|
ENABLE
|
||||||
|
DO BEGIN
|
||||||
|
UPDATE travel t
|
||||||
|
SET t.isDelivered = TRUE
|
||||||
|
WHERE t.shipped < util.VN_CURDATE();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -12,6 +12,7 @@ BEGIN
|
||||||
DECLARE vInvoiceFk INT;
|
DECLARE vInvoiceFk INT;
|
||||||
DECLARE vBookEntry INT;
|
DECLARE vBookEntry INT;
|
||||||
DECLARE vFiscalYear INT;
|
DECLARE vFiscalYear INT;
|
||||||
|
DECLARE vIncorrectInvoiceInDueDay INT;
|
||||||
|
|
||||||
DECLARE vInvoicesIn CURSOR FOR
|
DECLARE vInvoicesIn CURSOR FOR
|
||||||
SELECT DISTINCT e.invoiceInFk
|
SELECT DISTINCT e.invoiceInFk
|
||||||
|
@ -24,6 +25,19 @@ BEGIN
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
|
SELECT GROUP_CONCAT(ii.id) INTO vIncorrectInvoiceInDueDay
|
||||||
|
FROM invoiceInDueDay iidd
|
||||||
|
JOIN invoiceIn ii ON iidd.invoiceInFk = ii.id
|
||||||
|
JOIN `entry` e ON e.invoiceInFk = ii.id
|
||||||
|
JOIN duaEntry de ON de.entryFk = e.id
|
||||||
|
JOIN invoiceInConfig iic
|
||||||
|
WHERE de.duaFk = vDuaFk
|
||||||
|
AND iidd.dueDated <= util.VN_CURDATE() + INTERVAL iic.dueDateMarginDays DAY;
|
||||||
|
|
||||||
|
IF vIncorrectInvoiceInDueDay THEN
|
||||||
|
CALL util.throw(CONCAT('Incorrect due date, invoice: ', vIncorrectInvoiceInDueDay));
|
||||||
|
END IF;
|
||||||
|
|
||||||
UPDATE invoiceIn ii
|
UPDATE invoiceIn ii
|
||||||
JOIN entry e ON e.invoiceInFk = ii.id
|
JOIN entry e ON e.invoiceInFk = ii.id
|
||||||
JOIN duaEntry de ON de.entryFk = e.id
|
JOIN duaEntry de ON de.entryFk = e.id
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceInDueDay_calculate`(vInvoiceInFk INT)
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceInDueDay_calculate`(
|
||||||
|
vInvoiceInFk INT
|
||||||
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Calcula los vctos. de una factura recibida
|
* Calcula los vctos. de una factura recibida
|
||||||
|
@ -56,12 +58,13 @@ BEGIN
|
||||||
COUNT(DISTINCT(pdd.detail)) cont,
|
COUNT(DISTINCT(pdd.detail)) cont,
|
||||||
s.payDay,
|
s.payDay,
|
||||||
ii.issued,
|
ii.issued,
|
||||||
DATE(ii.created) + INTERVAL 2 DAY created
|
DATE(ii.created) + INTERVAL iic.dueDateMarginDays DAY created
|
||||||
FROM invoiceIn ii
|
FROM invoiceIn ii
|
||||||
JOIN invoiceInTax iit ON iit.invoiceInFk = ii.id
|
JOIN invoiceInTax iit ON iit.invoiceInFk = ii.id
|
||||||
LEFT JOIN sage.TiposIva ti ON ti.CodigoIva= iit.taxTypeSageFk
|
LEFT JOIN sage.TiposIva ti ON ti.CodigoIva= iit.taxTypeSageFk
|
||||||
JOIN supplier s ON s.id = ii.supplierFk
|
JOIN supplier s ON s.id = ii.supplierFk
|
||||||
JOIN payDemDetail pdd ON pdd.id = s.payDemFk
|
JOIN payDemDetail pdd ON pdd.id = s.payDemFk
|
||||||
|
JOIN invoiceInConfig iic
|
||||||
WHERE ii.id = vInvoiceInFk
|
WHERE ii.id = vInvoiceInFk
|
||||||
GROUP BY ii.id
|
GROUP BY ii.id
|
||||||
)sub
|
)sub
|
||||||
|
|
|
@ -98,6 +98,7 @@ proc: BEGIN
|
||||||
itemShelvingFk,
|
itemShelvingFk,
|
||||||
saleFk,
|
saleFk,
|
||||||
quantity,
|
quantity,
|
||||||
|
userFk,
|
||||||
isPicked)
|
isPicked)
|
||||||
SELECT vItemShelvingFk,
|
SELECT vItemShelvingFk,
|
||||||
vSaleFk,
|
vSaleFk,
|
||||||
|
|
|
@ -103,7 +103,7 @@ BEGIN
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
IF vIsItemShelvingSaleEmpty AND vQuantity <> vReservedQuantity THEN
|
IF vIsItemShelvingSaleEmpty AND vQuantity <> vReservedQuantity THEN
|
||||||
INSERT INTO itemShelvingSaleReserve (saleFk, vSectorFk)
|
INSERT INTO itemShelvingSaleReserve (saleFk, sectorFk)
|
||||||
SELECT vSaleFk, vSectorFk;
|
SELECT vSaleFk, vSectorFk;
|
||||||
CALL itemShelvingSale_reallocate(vItemShelvingFk, vItemFk, vSectorFk);
|
CALL itemShelvingSale_reallocate(vItemShelvingFk, vItemFk, vSectorFk);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
|
@ -240,7 +240,7 @@ BEGIN
|
||||||
NULL reference,
|
NULL reference,
|
||||||
NULL entityType,
|
NULL entityType,
|
||||||
NULL entityId,
|
NULL entityId,
|
||||||
'Inventario calculado',
|
'Inventario calculado' entityName,
|
||||||
@a invalue,
|
@a invalue,
|
||||||
NULL `out`,
|
NULL `out`,
|
||||||
@a balance,
|
@a balance,
|
||||||
|
|
|
@ -86,8 +86,8 @@ proc: BEGIN
|
||||||
WHERE calc_id = vCalcFk;
|
WHERE calc_id = vCalcFk;
|
||||||
|
|
||||||
UPDATE tmp.itemInventory it
|
UPDATE tmp.itemInventory it
|
||||||
JOIN tItemInventoryCalc iic ON iic.itemFk = it.id
|
LEFT JOIN tItemInventoryCalc iic ON iic.itemFk = it.id
|
||||||
JOIN tItemVisibleCalc ivc ON ivc.item_id = it.id
|
LEFT JOIN tItemVisibleCalc ivc ON ivc.item_id = it.id
|
||||||
SET it.inventory = iic.quantity,
|
SET it.inventory = iic.quantity,
|
||||||
it.visible = ivc.visible,
|
it.visible = ivc.visible,
|
||||||
it.avalaible = iic.quantity,
|
it.avalaible = iic.quantity,
|
||||||
|
@ -139,31 +139,35 @@ proc: BEGIN
|
||||||
CALL item_getAtp(vDate);
|
CALL item_getAtp(vDate);
|
||||||
CALL travel_upcomingArrivals(vWarehouseFk, vDate);
|
CALL travel_upcomingArrivals(vWarehouseFk, vDate);
|
||||||
|
|
||||||
UPDATE tmp.itemInventory ai
|
CREATE OR REPLACE TEMPORARY TABLE tItemAvailableCalc
|
||||||
JOIN (
|
(PRIMARY KEY (itemFk))
|
||||||
SELECT it.itemFk,
|
ENGINE = MEMORY
|
||||||
SUM(it.quantity) quantity,
|
SELECT it.itemFk,
|
||||||
im.quantity minQuantity
|
SUM(it.quantity) quantity,
|
||||||
FROM tmp.itemCalc it
|
im.quantity minQuantity
|
||||||
JOIN tmp.itemAtp im ON im.itemFk = it.itemFk
|
FROM tmp.itemCalc it
|
||||||
JOIN item i ON i.id = it.itemFk
|
JOIN tmp.itemAtp im ON im.itemFk = it.itemFk
|
||||||
LEFT JOIN origin o ON o.id = i.originFk
|
JOIN item i ON i.id = it.itemFk
|
||||||
LEFT JOIN tmp.itemTravel t ON t.wh = o.warehouseFk
|
LEFT JOIN origin o ON o.id = i.originFk
|
||||||
WHERE it.dated < IF(vMaxDays < 0 AND t.landing IS NOT NULL,
|
LEFT JOIN tmp.itemTravel t ON t.wh = o.warehouseFk
|
||||||
t.landing,
|
WHERE it.dated < IF(vMaxDays < 0 AND t.landing IS NOT NULL,
|
||||||
vDateToTomorrow)
|
t.landing,
|
||||||
GROUP BY it.itemFk
|
vDateToTomorrow)
|
||||||
) sub ON sub.itemFk = ai.id
|
GROUP BY it.itemFk;
|
||||||
SET ai.avalaible = IF(sub.minQuantity > 0,
|
|
||||||
ai.avalaible,
|
UPDATE tmp.itemInventory it
|
||||||
ai.avalaible + sub.minQuantity),
|
JOIN tItemAvailableCalc iac ON iac.itemFk = it.id
|
||||||
ai.sd = ai.inventory + sub.quantity;
|
SET it.avalaible = IF(iac.minQuantity > 0,
|
||||||
|
it.avalaible,
|
||||||
|
it.avalaible + iac.minQuantity),
|
||||||
|
it.sd = it.inventory + iac.quantity;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE
|
DROP TEMPORARY TABLE
|
||||||
tmp.itemTravel,
|
tmp.itemTravel,
|
||||||
tmp.itemCalc,
|
tmp.itemCalc,
|
||||||
tmp.itemAtp,
|
tmp.itemAtp,
|
||||||
tItemInventoryCalc,
|
tItemInventoryCalc,
|
||||||
tItemVisibleCalc;
|
tItemVisibleCalc,
|
||||||
|
tItemAvailableCalc;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -174,27 +174,30 @@ proc: BEGIN
|
||||||
WHERE NOT `lines`;
|
WHERE NOT `lines`;
|
||||||
|
|
||||||
-- Lineas por linea de encajado
|
-- Lineas por linea de encajado
|
||||||
|
CREATE OR REPLACE TEMPORARY TABLE tItemPackingType
|
||||||
|
(PRIMARY KEY(ticketFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT ticketFk,
|
||||||
|
SUM(sub.H) H,
|
||||||
|
SUM(sub.V) V,
|
||||||
|
SUM(sub.N) N
|
||||||
|
FROM (
|
||||||
|
SELECT t.ticketFk,
|
||||||
|
SUM(i.itemPackingTypeFk = 'H') H,
|
||||||
|
SUM(i.itemPackingTypeFk = 'V') V,
|
||||||
|
SUM(i.itemPackingTypeFk IS NULL) N
|
||||||
|
FROM tmp.productionTicket t
|
||||||
|
JOIN sale s ON s.ticketFk = t.ticketFk
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
GROUP BY t.ticketFk, i.itemPackingTypeFk
|
||||||
|
) sub
|
||||||
|
GROUP BY ticketFk;
|
||||||
|
|
||||||
UPDATE tmp.productionBuffer pb
|
UPDATE tmp.productionBuffer pb
|
||||||
JOIN (
|
JOIN tItemPackingType ti ON ti.ticketFk = pb.ticketFk
|
||||||
SELECT ticketFk,
|
SET pb.H = ti.H,
|
||||||
SUM(sub.H) H,
|
pb.V = ti.V,
|
||||||
SUM(sub.V) V,
|
pb.N = ti.N;
|
||||||
SUM(sub.N) N
|
|
||||||
FROM (
|
|
||||||
SELECT t.ticketFk,
|
|
||||||
SUM(i.itemPackingTypeFk = 'H') H,
|
|
||||||
SUM(i.itemPackingTypeFk = 'V') V,
|
|
||||||
SUM(i.itemPackingTypeFk IS NULL) N
|
|
||||||
FROM tmp.productionTicket t
|
|
||||||
JOIN sale s ON s.ticketFk = t.ticketFk
|
|
||||||
JOIN item i ON i.id = s.itemFk
|
|
||||||
GROUP BY t.ticketFk, i.itemPackingTypeFk
|
|
||||||
) sub
|
|
||||||
GROUP BY ticketFk
|
|
||||||
) sub2 ON sub2.ticketFk = pb.ticketFk
|
|
||||||
SET pb.H = sub2.H,
|
|
||||||
pb.V = sub2.V,
|
|
||||||
pb.N = sub2.N;
|
|
||||||
|
|
||||||
-- Colecciones segun tipo de encajado
|
-- Colecciones segun tipo de encajado
|
||||||
UPDATE tmp.productionBuffer pb
|
UPDATE tmp.productionBuffer pb
|
||||||
|
@ -273,6 +276,7 @@ proc: BEGIN
|
||||||
tmp.risk,
|
tmp.risk,
|
||||||
tmp.ticket_problems,
|
tmp.ticket_problems,
|
||||||
tmp.ticketWithPrevia,
|
tmp.ticketWithPrevia,
|
||||||
tItemShelvingStock;
|
tItemShelvingStock,
|
||||||
|
tItemPackingType;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -10,15 +10,10 @@ BEGIN
|
||||||
* @param vSaleGroupFk id de la preparación previa
|
* @param vSaleGroupFk id de la preparación previa
|
||||||
* @param vParkingFk id del parking
|
* @param vParkingFk id del parking
|
||||||
*/
|
*/
|
||||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
|
||||||
BEGIN
|
|
||||||
RESIGNAL;
|
|
||||||
END;
|
|
||||||
|
|
||||||
UPDATE saleGroup sg
|
UPDATE saleGroup sg
|
||||||
SET sg.parkingFk = vParkingFk
|
SET sg.parkingFk = vParkingFk
|
||||||
WHERE sg.id = vSaleGroupFk
|
WHERE sg.id = vSaleGroupFk
|
||||||
AND sg.created >= util.VN_CURDATE() - INTERVAL 1 WEEK;
|
AND sg.created >= util.VN_CURDATE() - INTERVAL 1 WEEK;
|
||||||
|
|
||||||
CALL ticket_setNextState(ticket_get(vSaleGroupFk));
|
CALL ticket_setNextState(ticket_get(vSaleGroupFk));
|
||||||
END$$
|
END$$
|
||||||
|
|
|
@ -13,12 +13,6 @@ BEGIN
|
||||||
DECLARE vParkingFk INT;
|
DECLARE vParkingFk INT;
|
||||||
DECLARE vLastWeek DATE;
|
DECLARE vLastWeek DATE;
|
||||||
|
|
||||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
|
||||||
BEGIN
|
|
||||||
ROLLBACK;
|
|
||||||
RESIGNAL;
|
|
||||||
END;
|
|
||||||
|
|
||||||
SET vParkingCode = REPLACE(vParkingCode, ' ', '');
|
SET vParkingCode = REPLACE(vParkingCode, ' ', '');
|
||||||
|
|
||||||
SELECT id INTO vParkingFk
|
SELECT id INTO vParkingFk
|
||||||
|
@ -29,8 +23,6 @@ BEGIN
|
||||||
CALL util.throw('parkingNotExist');
|
CALL util.throw('parkingNotExist');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
START TRANSACTION;
|
|
||||||
|
|
||||||
SET vLastWeek = util.VN_CURDATE() - INTERVAL 1 WEEK;
|
SET vLastWeek = util.VN_CURDATE() - INTERVAL 1 WEEK;
|
||||||
|
|
||||||
-- Comprobamos si es una prep. previa, ticket, colección o shelving
|
-- Comprobamos si es una prep. previa, ticket, colección o shelving
|
||||||
|
@ -45,7 +37,5 @@ BEGIN
|
||||||
ELSE
|
ELSE
|
||||||
CALL util.throw('paramNotExist');
|
CALL util.throw('paramNotExist');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`shelving_setParking`(IN `vShelvingCode` VARCHAR(8), IN `vParkingFk` INT)
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`shelving_setParking`(IN `vShelvingCode` VARCHAR(8), IN `vParkingFk` INT)
|
||||||
proc: BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Aparca una matrícula en un parking
|
* Aparca una matrícula en un parking
|
||||||
*
|
*
|
||||||
* @param vShelvingCode code de la matrícula
|
* @param vShelvingCode code de la matrícula
|
||||||
* @param vParkingFk id del parking
|
* @param vParkingFk id del parking
|
||||||
*/
|
*/
|
||||||
INSERT INTO vn.shelvingLog (originFk, userFk, action , description,changedModel,changedModelId)
|
INSERT INTO shelvingLog (originFk, userFk, action , description,changedModel,changedModelId)
|
||||||
SELECT s.id, account.myUser_getId(), 'update', CONCAT("Cambio parking ",vShelvingCode," de ", p.code," a ", pNew.code),'Shelving',s.id
|
SELECT s.id, account.myUser_getId(), 'update', CONCAT("Cambio parking ",vShelvingCode," de ", p.code," a ", pNew.code),'Shelving',s.id
|
||||||
FROM parking p
|
FROM parking p
|
||||||
JOIN shelving s ON s.parkingFk = p.id
|
JOIN shelving s ON s.parkingFk = p.id
|
||||||
JOIN parking pNew ON pNew.id = vParkingFk
|
JOIN parking pNew ON pNew.id = vParkingFk
|
||||||
WHERE s.code = vShelvingCode COLLATE utf8_unicode_ci;
|
WHERE s.code = vShelvingCode COLLATE utf8_unicode_ci;
|
||||||
|
|
||||||
UPDATE vn.shelving
|
UPDATE shelving
|
||||||
SET parkingFk = vParkingFk,
|
SET parkingFk = vParkingFk,
|
||||||
parked = util.VN_NOW(),
|
parked = util.VN_NOW(),
|
||||||
isPrinted = TRUE
|
isPrinted = TRUE
|
||||||
|
|
|
@ -21,11 +21,6 @@ BEGIN
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
|
||||||
BEGIN
|
|
||||||
RESIGNAL;
|
|
||||||
END;
|
|
||||||
|
|
||||||
INSERT INTO vn.ticketParking(ticketFk, parkingFk)
|
INSERT INTO vn.ticketParking(ticketFk, parkingFk)
|
||||||
SELECT IFNULL(tc2.ticketFk, t.id), vParkingFk
|
SELECT IFNULL(tc2.ticketFk, t.id), vParkingFk
|
||||||
FROM ticket t
|
FROM ticket t
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_splitItemPackingType`(
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_splitItemPackingType`(
|
||||||
vSelf INT,
|
vSelf INT,
|
||||||
vItemPackingTypeFk VARCHAR(1)
|
vOriginalItemPackingTypeFk VARCHAR(1)
|
||||||
)
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ BEGIN
|
||||||
* Respeta el id inicial para el tipo propuesto.
|
* Respeta el id inicial para el tipo propuesto.
|
||||||
*
|
*
|
||||||
* @param vSelf Id ticket
|
* @param vSelf Id ticket
|
||||||
* @param vItemPackingTypeFk Tipo para el que se reserva el número de ticket original
|
* @param vOriginalItemPackingTypeFk Tipo para el que se reserva el número de ticket original
|
||||||
* @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk)
|
* @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk)
|
||||||
*/
|
*/
|
||||||
DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H';
|
DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H';
|
||||||
|
@ -23,7 +23,7 @@ BEGIN
|
||||||
SELECT itemPackingTypeFk
|
SELECT itemPackingTypeFk
|
||||||
FROM tSaleGroup
|
FROM tSaleGroup
|
||||||
WHERE itemPackingTypeFk IS NOT NULL
|
WHERE itemPackingTypeFk IS NOT NULL
|
||||||
ORDER BY (itemPackingTypeFk = vItemPackingTypeFk) DESC;
|
ORDER BY (itemPackingTypeFk = vOriginalItemPackingTypeFk) DESC;
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.invoiceInConfig
|
||||||
|
ADD dueDateMarginDays INT UNSIGNED DEFAULT 2 NULL;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.calendar
|
||||||
|
ADD CONSTRAINT calendar_user_FK FOREIGN KEY (editorFk) REFERENCES account.`user`(id);
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE IF EXISTS vn.itemShelving
|
||||||
|
MODIFY COLUMN IF EXISTS isSplit tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Este valor cambia al splitar un carro que se ha quedado en holanda';
|
|
@ -1,62 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Route summary path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('employee', 'route');
|
|
||||||
await page.waitToClick(selectors.routeIndex.previewButton);
|
|
||||||
await page.waitToClick(selectors.routeSummary.goToRouteSummaryButton);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reach the first route summary section', async() => {
|
|
||||||
await page.waitForState('route.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should display details from the route on the header`, async() => {
|
|
||||||
await page.waitForTextInElement(selectors.routeSummary.header, 'first route');
|
|
||||||
const result = await page.waitToGetProperty(selectors.routeSummary.header, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('first route');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display some route details like the cost', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.routeSummary.cost, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('€10.00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should click on the first ticket ID making the descriptor popover visible', async() => {
|
|
||||||
await page.waitForState('route.card.summary');
|
|
||||||
await page.waitForTimeout(250);
|
|
||||||
await page.waitToClick(selectors.routeSummary.firstTicketID);
|
|
||||||
await page.waitForSelector(selectors.routeSummary.firstTicketDescriptor);
|
|
||||||
const visible = await page.isVisible(selectors.routeSummary.firstTicketDescriptor);
|
|
||||||
|
|
||||||
expect(visible).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should close the ticket descriptor', async() => {
|
|
||||||
await page.closePopup();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should click on the first alias making the client descriptor popover visible', async() => {
|
|
||||||
await page.waitToClick(selectors.routeSummary.firstAlias);
|
|
||||||
await page.waitForSelector(selectors.routeSummary.firstClientDescriptor);
|
|
||||||
const visible = await page.isVisible(selectors.routeSummary.firstClientDescriptor);
|
|
||||||
|
|
||||||
expect(visible).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should close the client descriptor', async() => {
|
|
||||||
await page.closePopup();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,42 +0,0 @@
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Route basic Data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('delivery', 'route');
|
|
||||||
await page.accessToSearchResult('1');
|
|
||||||
await page.accessToSection('route.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit the route basic data and confirm the route was edited', async() => {
|
|
||||||
const nextMonth = Date.vnNew();
|
|
||||||
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
|
||||||
nextMonth.setUTCHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const form = 'vn-route-basic-data form';
|
|
||||||
const values = {
|
|
||||||
worker: 'adminBossNick',
|
|
||||||
vehicle: '1111-IMK',
|
|
||||||
created: nextMonth,
|
|
||||||
kmStart: 1,
|
|
||||||
kmEnd: 2,
|
|
||||||
started: '08:00',
|
|
||||||
finished: '12:30',
|
|
||||||
};
|
|
||||||
|
|
||||||
const message = await page.sendForm(form, values);
|
|
||||||
await page.reloadSection('route.card.basicData');
|
|
||||||
const formValues = await page.fetchForm(form, Object.keys(values));
|
|
||||||
|
|
||||||
expect(message.isSuccess).toBeTrue();
|
|
||||||
expect(formValues).toEqual(values);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,91 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Route create path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('employee', 'route');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('as employee', () => {
|
|
||||||
it('should click on the add new route button and open the creation form', async() => {
|
|
||||||
await page.waitToClick(selectors.routeIndex.addNewRouteButton);
|
|
||||||
await page.waitForState('route.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should attempt to create a new route but fail since employee has no access rights`, async() => {
|
|
||||||
await page.write(selectors.createRouteView.description, 'faster faster!!');
|
|
||||||
await page.waitToClick(selectors.createRouteView.submitButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Access Denied');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('as delivery', () => {
|
|
||||||
beforeAll(async() => {
|
|
||||||
await page.login('delivery');
|
|
||||||
await page.selectModule('route');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should again click on the add new route button and open the creation form', async() => {
|
|
||||||
await page.waitToClick(selectors.routeIndex.addNewRouteButton);
|
|
||||||
await page.waitForState('route.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should create a new route`, async() => {
|
|
||||||
await page.autocompleteSearch(selectors.createRouteView.worker, 'teamManagerNick');
|
|
||||||
await page.pickDate(selectors.createRouteView.createdDatePicker);
|
|
||||||
await page.autocompleteSearch(selectors.createRouteView.vehicleAuto, '4444-IMK');
|
|
||||||
await page.autocompleteSearch(selectors.createRouteView.agency, 'Teleportation device');
|
|
||||||
await page.write(selectors.createRouteView.description, 'faster faster!!');
|
|
||||||
await page.waitToClick(selectors.createRouteView.submitButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the redirection to the created route summary`, async() => {
|
|
||||||
await page.waitForState('route.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should navigate back to the route index`, async() => {
|
|
||||||
await page.waitToClick(selectors.globalItems.returnToModuleIndexButton);
|
|
||||||
await page.waitForState('route.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
let count;
|
|
||||||
it(`should count the amount of routes before clonation`, async() => {
|
|
||||||
await page.waitForFunction(selector => {
|
|
||||||
return document.querySelectorAll(selector).length > 6;
|
|
||||||
}, {}, selectors.routeIndex.anyResult);
|
|
||||||
count = await page.countElement(selectors.routeIndex.anyResult);
|
|
||||||
|
|
||||||
expect(count).toBeGreaterThanOrEqual(7);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should clone the first route`, async() => {
|
|
||||||
await page.waitToClick(selectors.routeIndex.firstRouteCheckbox);
|
|
||||||
await page.waitToClick(selectors.routeIndex.cloneButton);
|
|
||||||
await page.waitToClick(selectors.routeIndex.submitClonationButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should reload the section and count the amount of routes after clonation`, async() => {
|
|
||||||
await page.waitForNumberOfElements(selectors.routeIndex.anyResult, count + 1);
|
|
||||||
const result = await page.countElement(selectors.routeIndex.anyResult);
|
|
||||||
|
|
||||||
expect(result).toEqual(count + 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,59 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Route tickets path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('delivery', 'route');
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
await page.accessToSection('route.card.tickets');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should modify the first ticket priority', async() => {
|
|
||||||
await page.writeOnEditableTD(selectors.routeTickets.firstTicketPriority, '9');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the buscaman button is disabled', async() => {
|
|
||||||
await page.waitForSelector(`${selectors.routeTickets.buscamanButton}.disabled`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the first ticket checkbox and confirm the buscamanButton button is no longer disabled', async() => {
|
|
||||||
await page.waitForSelector(`${selectors.routeTickets.buscamanButton}.disabled`, {visible: false});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the route volume on the descriptor', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.routeDescriptor.volume, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toEqual('0.2 / 50 m³');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should count how many tickets are in route', async() => {
|
|
||||||
const result = await page.countElement(selectors.routeTickets.anyTicket);
|
|
||||||
|
|
||||||
expect(result).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the first ticket in route', async() => {
|
|
||||||
await page.waitToClick(selectors.routeTickets.firstTicketDeleteButton);
|
|
||||||
await page.waitToClick(selectors.routeTickets.confirmButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Ticket removed from route');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should now count how many tickets are in route to find one less', async() => {
|
|
||||||
await page.waitForNumberOfElements(selectors.routeTickets.anyTicket, 0);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -4,7 +4,17 @@ import getMainRoute from 'core/lib/get-main-route';
|
||||||
config.$inject = ['$stateProvider', '$urlRouterProvider'];
|
config.$inject = ['$stateProvider', '$urlRouterProvider'];
|
||||||
function config($stateProvider, $urlRouterProvider) {
|
function config($stateProvider, $urlRouterProvider) {
|
||||||
$urlRouterProvider
|
$urlRouterProvider
|
||||||
.otherwise('/');
|
.otherwise(async($injector, {$location}) => {
|
||||||
|
const prefix = '#!';
|
||||||
|
if (!$location.$$path) return window.location.href = `/${prefix}/`;
|
||||||
|
|
||||||
|
const url = $location.$$absUrl
|
||||||
|
.replace('5000', '9000')
|
||||||
|
.replace('salix', 'lilium')
|
||||||
|
.replace(prefix, '#')
|
||||||
|
.replace('client', 'customer');
|
||||||
|
window.location.href = url;
|
||||||
|
});
|
||||||
|
|
||||||
$stateProvider
|
$stateProvider
|
||||||
.state('layout', {
|
.state('layout', {
|
||||||
|
|
|
@ -367,5 +367,6 @@
|
||||||
"It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono",
|
"It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono",
|
||||||
"Payment method is required": "El método de pago es obligatorio",
|
"Payment method is required": "El método de pago es obligatorio",
|
||||||
"Cannot send mail": "Não é possível enviar o email",
|
"Cannot send mail": "Não é possível enviar o email",
|
||||||
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos"
|
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
|
||||||
}
|
"The sale not exists in the item shelving": "La venta no existe en la estantería del artículo"
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ module.exports = Self => {
|
||||||
SELECT COUNT(*) > 0 isCustomer
|
SELECT COUNT(*) > 0 isCustomer
|
||||||
FROM salix.Account A
|
FROM salix.Account A
|
||||||
JOIN salix.Role r ON r.id = A.roleFK
|
JOIN salix.Role r ON r.id = A.roleFK
|
||||||
WHERE r.name = 'customer'
|
WHERE r.name IN ('customer', 'supplier')
|
||||||
AND A.id IN (?)`;
|
AND A.id IN (?)`;
|
||||||
const [result] = await Self.rawSql(query, [id], myOptions);
|
const [result] = await Self.rawSql(query, [id], myOptions);
|
||||||
const {isCustomer} = result;
|
const {isCustomer} = result;
|
||||||
|
|
|
@ -95,6 +95,16 @@ module.exports = Self => {
|
||||||
type: 'date',
|
type: 'date',
|
||||||
description: `The to date filter`
|
description: `The to date filter`
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
arg: 'fromShipped',
|
||||||
|
type: 'date',
|
||||||
|
description: `The from shipped date filter`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'toShipped',
|
||||||
|
type: 'date',
|
||||||
|
description: `The to shipped date filter`
|
||||||
|
},
|
||||||
{
|
{
|
||||||
arg: 'days',
|
arg: 'days',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
|
@ -133,8 +143,12 @@ module.exports = Self => {
|
||||||
return {'e.created': {gte: value}};
|
return {'e.created': {gte: value}};
|
||||||
case 'from':
|
case 'from':
|
||||||
return {'t.landed': {gte: value}};
|
return {'t.landed': {gte: value}};
|
||||||
|
case 'fromShipped':
|
||||||
|
return {'t.shipped': {gte: value}};
|
||||||
case 'to':
|
case 'to':
|
||||||
return {'t.landed': {lte: value}};
|
return {'t.landed': {lte: value}};
|
||||||
|
case 'toShipped':
|
||||||
|
return {'t.shipped': {lte: value}};
|
||||||
case 'id':
|
case 'id':
|
||||||
case 'isBooked':
|
case 'isBooked':
|
||||||
case 'isConfirmed':
|
case 'isConfirmed':
|
||||||
|
|
|
@ -82,7 +82,15 @@ module.exports = Self => {
|
||||||
{
|
{
|
||||||
arg: 'correctedFk',
|
arg: 'correctedFk',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'The corrected invoice',
|
description: 'The rectified invoice',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'correctingFk',
|
||||||
|
type: 'Boolean',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'supplierActivityFk',
|
||||||
|
type: 'string',
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -111,6 +119,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let correctings;
|
let correctings;
|
||||||
|
let correcteds;
|
||||||
if (args.correctedFk) {
|
if (args.correctedFk) {
|
||||||
correctings = await models.InvoiceInCorrection.find({
|
correctings = await models.InvoiceInCorrection.find({
|
||||||
fields: ['correctingFk'],
|
fields: ['correctingFk'],
|
||||||
|
@ -118,6 +127,9 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.correctingFk || args.correctingFk === false)
|
||||||
|
correcteds = await models.InvoiceInCorrection.find();
|
||||||
|
|
||||||
const where = buildFilter(ctx.args, (param, value) => {
|
const where = buildFilter(ctx.args, (param, value) => {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 'search':
|
case 'search':
|
||||||
|
@ -141,8 +153,14 @@ module.exports = Self => {
|
||||||
return {[`ii.${param}`]: value};
|
return {[`ii.${param}`]: value};
|
||||||
case 'awbCode':
|
case 'awbCode':
|
||||||
return {'sub.code': value};
|
return {'sub.code': value};
|
||||||
|
case 'correctingFk':
|
||||||
|
return args.correctingFk
|
||||||
|
? {'ii.id': {inq: correcteds.map(x => x.correctingFk)}}
|
||||||
|
: {'ii.id': {nin: correcteds.map(x => x.correctingFk)}};
|
||||||
case 'correctedFk':
|
case 'correctedFk':
|
||||||
return {'ii.id': {inq: correctings.map(x => x.correctingFk)}};
|
return {'ii.id': {inq: correctings.map(x => x.correctingFk)}};
|
||||||
|
case 'supplierActivityFk':
|
||||||
|
return {'s.supplierActivityFk': value};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('updateFromSale', {
|
Self.remoteMethod('updateFromSale', {
|
||||||
description: 'Update the visible items',
|
description: 'Update the visible items',
|
||||||
|
@ -32,6 +33,9 @@ module.exports = Self => {
|
||||||
include: {relation: 'itemShelving'}
|
include: {relation: 'itemShelving'}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
|
if (!itemShelvingSale?.itemShelving())
|
||||||
|
throw new UserError('The sale not exists in the item shelving');
|
||||||
|
|
||||||
const itemShelving = itemShelvingSale.itemShelving();
|
const itemShelving = itemShelvingSale.itemShelving();
|
||||||
const quantity = itemShelving.visible + itemShelvingSale.quantity;
|
const quantity = itemShelving.visible + itemShelvingSale.quantity;
|
||||||
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Agencies"
|
|
||||||
data="agencies">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pt-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
url="AgencyModes"
|
|
||||||
label="Agency route"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="filter.agencyModeFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
data="agencies"
|
|
||||||
label="Agency Agreement"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="filter.agencyFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<section class="vn-px-md">
|
|
||||||
<vn-horizontal class="manifold-panel vn-pa-md">
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="From"
|
|
||||||
ng-model="filter.from"
|
|
||||||
on-change="$ctrl.from = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="To"
|
|
||||||
ng-model="filter.to"
|
|
||||||
on-change="$ctrl.to = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,17 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
class Controller extends SearchPanel {
|
|
||||||
get filter() {
|
|
||||||
return this.$.filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
set filter(value = {}) {
|
|
||||||
this.$.filter = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAgencyTermSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
Search by invoiceIn id or autonomous name: Buscar por id de recibida o por nombre de autónomo
|
|
||||||
Search autonomous: Buscar autónomos
|
|
|
@ -1,108 +0,0 @@
|
||||||
<mg-ajax path="dms/upload" options="vnPost"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.dms">
|
|
||||||
</vn-watcher>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Companies"
|
|
||||||
data="companies"
|
|
||||||
order="code">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="DmsTypes"
|
|
||||||
data="dmsTypes"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-ma-md"
|
|
||||||
enctype="multipart/form-data">
|
|
||||||
<div class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
vn-focus
|
|
||||||
label="Reference"
|
|
||||||
ng-model="$ctrl.dms.reference"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Company"
|
|
||||||
ng-model="$ctrl.dms.companyId"
|
|
||||||
data="companies"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="$ctrl.dms.warehouseId"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Type"
|
|
||||||
ng-model="$ctrl.dms.dmsTypeId"
|
|
||||||
data="dmsTypes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.dms.description"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-file
|
|
||||||
vn-one
|
|
||||||
label="File"
|
|
||||||
ng-model="$ctrl.dms.files"
|
|
||||||
on-change="$ctrl.onFileChange($files)"
|
|
||||||
accept="{{$ctrl.allowedContentTypes}}"
|
|
||||||
required="true"
|
|
||||||
multiple="true">
|
|
||||||
<append>
|
|
||||||
<vn-icon vn-none
|
|
||||||
color-marginal
|
|
||||||
title="{{$ctrl.contentTypesInfo}}"
|
|
||||||
icon="info">
|
|
||||||
</vn-icon>
|
|
||||||
</append>
|
|
||||||
</vn-input-file>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check
|
|
||||||
label="Generate identifier for original file"
|
|
||||||
ng-model="$ctrl.dms.hasFile">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Upload">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="client.card.dms.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
|
@ -1,120 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
import UserError from 'core/lib/user-error';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
this.dms = {
|
|
||||||
files: [],
|
|
||||||
hasFile: false,
|
|
||||||
hasFileAttached: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get route() {
|
|
||||||
return this._route;
|
|
||||||
}
|
|
||||||
|
|
||||||
set route(value) {
|
|
||||||
this._route = value;
|
|
||||||
|
|
||||||
this.setDefaultParams();
|
|
||||||
this.getAllowedContentTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
$onChanges() {
|
|
||||||
if (this.$params && this.$params.q)
|
|
||||||
this.params = JSON.parse(this.$params.q);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllowedContentTypes() {
|
|
||||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
|
||||||
const contentTypes = res.data.join(', ');
|
|
||||||
this.allowedContentTypes = contentTypes;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get contentTypesInfo() {
|
|
||||||
return this.$t('ContentTypesInfo', {
|
|
||||||
allowedContentTypes: this.allowedContentTypes
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setDefaultParams() {
|
|
||||||
const params = {filter: {
|
|
||||||
where: {code: 'invoiceIn'}
|
|
||||||
}};
|
|
||||||
this.$http.get('DmsTypes/findOne', {params}).then(res => {
|
|
||||||
const dmsType = res.data && res.data;
|
|
||||||
const companyId = this.vnConfig.companyFk;
|
|
||||||
const warehouseId = this.vnConfig.warehouseFk;
|
|
||||||
const defaultParams = {
|
|
||||||
warehouseId: warehouseId,
|
|
||||||
companyId: companyId,
|
|
||||||
dmsTypeId: dmsType.id,
|
|
||||||
description: this.params.supplierName
|
|
||||||
};
|
|
||||||
|
|
||||||
this.dms = Object.assign(this.dms, defaultParams);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
if (this.dms.files.length > 1) throw new UserError('You cannot attach more than one document');
|
|
||||||
const query = `dms/uploadFile`;
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
url: query,
|
|
||||||
params: this.dms,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': undefined
|
|
||||||
},
|
|
||||||
transformRequest: files => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(files[0].name, files[0]);
|
|
||||||
return formData;
|
|
||||||
},
|
|
||||||
data: this.dms.files
|
|
||||||
};
|
|
||||||
this.$http(options).then(res => {
|
|
||||||
if (res) {
|
|
||||||
const addedDms = res.data;
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
rows: this.params.rows,
|
|
||||||
dms: addedDms
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.post('AgencyTerms/createInvoiceIn', params)
|
|
||||||
.then(() => {
|
|
||||||
this.$state.go('route.agencyTerm.index');
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileChange(files) {
|
|
||||||
let hasFileAttached = false;
|
|
||||||
|
|
||||||
if (files.length > 0)
|
|
||||||
hasFileAttached = true;
|
|
||||||
|
|
||||||
this.$.$applyAsync(() => {
|
|
||||||
this.dms.hasFileAttached = hasFileAttached;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAgencyTermCreateInvoiceIn', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,107 +0,0 @@
|
||||||
import './index';
|
|
||||||
import watcher from 'core/mocks/watcher.js';
|
|
||||||
|
|
||||||
describe('AgencyTerm', () => {
|
|
||||||
describe('Component vnAgencyTermCreateInvoiceIn', () => {
|
|
||||||
let controller;
|
|
||||||
let $scope;
|
|
||||||
let $httpBackend;
|
|
||||||
let $httpParamSerializer;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
|
||||||
const $element = angular.element('<vn-agency-term-create-invoice-in></vn-agency-term-create-invoice-in>');
|
|
||||||
controller = $componentController('vnAgencyTermCreateInvoiceIn', {$element});
|
|
||||||
controller._route = {
|
|
||||||
id: 1
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('$onChanges()', () => {
|
|
||||||
it('should update the params data when $params.q is defined', () => {
|
|
||||||
controller.$params = {q: '{"supplierName": "Plants SL","rows": null}'};
|
|
||||||
|
|
||||||
const params = {q: '{"supplierName": "Plants SL", "rows": null}'};
|
|
||||||
const json = JSON.parse(params.q);
|
|
||||||
|
|
||||||
controller.$onChanges();
|
|
||||||
|
|
||||||
expect(controller.params).toEqual(json);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('route() setter', () => {
|
|
||||||
it('should set the ticket data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
|
||||||
jest.spyOn(controller, 'setDefaultParams');
|
|
||||||
jest.spyOn(controller, 'getAllowedContentTypes');
|
|
||||||
controller.route = {
|
|
||||||
id: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(controller.route).toBeDefined();
|
|
||||||
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
|
||||||
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getAllowedContentTypes()', () => {
|
|
||||||
it('should make an HTTP GET request to get the allowed content types', () => {
|
|
||||||
const expectedResponse = ['image/png', 'image/jpg'];
|
|
||||||
$httpBackend.expect('GET', `DmsContainers/allowedContentTypes`).respond(expectedResponse);
|
|
||||||
controller.getAllowedContentTypes();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.allowedContentTypes).toBeDefined();
|
|
||||||
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setDefaultParams()', () => {
|
|
||||||
it('should perform a GET query and define the dms property on controller', () => {
|
|
||||||
const params = {filter: {
|
|
||||||
where: {code: 'invoiceIn'}
|
|
||||||
}};
|
|
||||||
const serializedParams = $httpParamSerializer(params);
|
|
||||||
$httpBackend.expect('GET', `DmsTypes/findOne?${serializedParams}`).respond({id: 1, code: 'invoiceIn'});
|
|
||||||
controller.params = {supplierName: 'Plants SL'};
|
|
||||||
controller.setDefaultParams();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.dms).toBeDefined();
|
|
||||||
expect(controller.dms.dmsTypeId).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
|
||||||
it('should make an HTTP POST request to save the form data', () => {
|
|
||||||
controller.$.watcher = watcher;
|
|
||||||
|
|
||||||
jest.spyOn(controller.$.watcher, 'updateOriginalData');
|
|
||||||
const files = [{id: 1, name: 'MyFile'}];
|
|
||||||
controller.dms = {files};
|
|
||||||
const serializedParams = $httpParamSerializer(controller.dms);
|
|
||||||
const query = `dms/uploadFile?${serializedParams}`;
|
|
||||||
controller.params = {rows: null};
|
|
||||||
|
|
||||||
$httpBackend.expect('POST', query).respond({});
|
|
||||||
$httpBackend.expect('POST', 'AgencyTerms/createInvoiceIn').respond({});
|
|
||||||
controller.onSubmit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onFileChange()', () => {
|
|
||||||
it('should set dms hasFileAttached property to true if has any files', () => {
|
|
||||||
const files = [{id: 1, name: 'MyFile'}];
|
|
||||||
controller.onFileChange(files);
|
|
||||||
$scope.$apply();
|
|
||||||
|
|
||||||
expect(controller.dms.hasFileAttached).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,7 +0,0 @@
|
||||||
vn-ticket-request {
|
|
||||||
.vn-textfield {
|
|
||||||
margin: 0!important;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="AgencyTerms/filter"
|
|
||||||
data="agencyTerms"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
auto-state="false"
|
|
||||||
panel="vn-agency-term-search-panel"
|
|
||||||
info="Search by invoiceIn id or autonomous name"
|
|
||||||
placeholder="Search autonomous"
|
|
||||||
filter="{}"
|
|
||||||
model="model">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-card>
|
|
||||||
<smart-table
|
|
||||||
model="model"
|
|
||||||
options="$ctrl.smartTableOptions"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
<slot-actions>
|
|
||||||
<div>
|
|
||||||
<div class="totalBox" style="text-align: center;">
|
|
||||||
<h6 translate>Total</h6>
|
|
||||||
<vn-label-value
|
|
||||||
label="Price"
|
|
||||||
value="{{$ctrl.totalPrice | currency: 'EUR': 2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</slot-actions>
|
|
||||||
<slot-table>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</th>
|
|
||||||
<th shrink field="routeFk">
|
|
||||||
<span translate>Id</span>
|
|
||||||
</th>
|
|
||||||
<th field="created">
|
|
||||||
<span translate>Date</span>
|
|
||||||
</th>
|
|
||||||
<th field="agencyModeFk">
|
|
||||||
<span translate>Agency route</span>
|
|
||||||
</th>
|
|
||||||
<th field="agencyFk">
|
|
||||||
<span translate>Agency Agreement</span>
|
|
||||||
</th>
|
|
||||||
<th field="packages">
|
|
||||||
<span translate>Packages</span>
|
|
||||||
</th>
|
|
||||||
<th field="m3">
|
|
||||||
<span translate>M3</span>
|
|
||||||
</th>
|
|
||||||
<th field="kmTotal">
|
|
||||||
<span translate>Km</span>
|
|
||||||
</th>
|
|
||||||
<th field="price">
|
|
||||||
<span translate>Price</span>
|
|
||||||
</th>
|
|
||||||
<th field="invoiceInFk">
|
|
||||||
<span translate>Received</span>
|
|
||||||
</th>
|
|
||||||
<th field="supplierFk">
|
|
||||||
<span translate>Autonomous</span>
|
|
||||||
</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="agencyTerm in agencyTerms">
|
|
||||||
<td shrink>
|
|
||||||
<vn-check
|
|
||||||
ng-model="agencyTerm.checked"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-check>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
title="{{::agencyTerm.id}}"
|
|
||||||
vn-click-stop="routeDescriptor.show($event, agencyTerm.routeFk)"
|
|
||||||
class="link">
|
|
||||||
{{::agencyTerm.routeFk}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td shrink-date>{{::agencyTerm.created | date:'dd/MM/yyyy'}}</td>
|
|
||||||
<td>{{::agencyTerm.agencyModeName | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.agencyAgreement | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.packages | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.m3 | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.kmTotal | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.price | dashIfEmpty}}</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
vn-click-stop="invoiceInDescriptor.show($event, agencyTerm.invoiceInFk)"
|
|
||||||
class="link">
|
|
||||||
{{::agencyTerm.invoiceInFk}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
class="link"
|
|
||||||
vn-click-stop="supplierDescriptor.show($event, agencyTerm.supplierFk)">
|
|
||||||
{{::agencyTerm.supplierName}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(agencyTerm.route)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</slot-table>
|
|
||||||
</smart-table>
|
|
||||||
</vn-card>
|
|
||||||
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-route-summary
|
|
||||||
route="$ctrl.routeSelected">
|
|
||||||
</vn-route-summary>
|
|
||||||
</vn-popup>
|
|
||||||
|
|
||||||
<vn-route-descriptor-popover
|
|
||||||
vn-id="routeDescriptor">
|
|
||||||
</vn-route-descriptor-popover>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
||||||
<vn-invoice-in-descriptor-popover
|
|
||||||
vn-id="invoiceInDescriptor">
|
|
||||||
</vn-invoice-in-descriptor-popover>
|
|
||||||
|
|
||||||
<div fixed-bottom-right>
|
|
||||||
<vn-vertical style="align-items: center;">
|
|
||||||
<vn-button class="round sm vn-mb-sm"
|
|
||||||
icon="icon-invoice-in-create"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.createInvoiceIn()"
|
|
||||||
vn-tooltip="Create invoiceIn"
|
|
||||||
tooltip-position="left">
|
|
||||||
</vn-button>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
|
|
@ -1,121 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
this.smartTableOptions = {
|
|
||||||
activeButtons: {
|
|
||||||
search: true
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
field: 'agencyModeFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'AgencyModes',
|
|
||||||
showField: 'name',
|
|
||||||
valueField: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'agencyFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Agencies',
|
|
||||||
showField: 'name',
|
|
||||||
valueField: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'supplierFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Suppliers',
|
|
||||||
showField: 'name',
|
|
||||||
valueField: 'name',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'agencyModeFk':
|
|
||||||
return {'a.agencyModeFk': value};
|
|
||||||
case 'supplierFk':
|
|
||||||
return {'a.supplierName': value};
|
|
||||||
case 'routeFk':
|
|
||||||
return {'a.routeFk': value};
|
|
||||||
case 'created':
|
|
||||||
case 'agencyFk':
|
|
||||||
case 'packages':
|
|
||||||
case 'm3':
|
|
||||||
case 'kmTotal':
|
|
||||||
case 'price':
|
|
||||||
case 'invoiceInFk':
|
|
||||||
return {[`a.${param}`]: value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get checked() {
|
|
||||||
const agencyTerms = this.$.model.data || [];
|
|
||||||
const checkedAgencyTerms = [];
|
|
||||||
for (let agencyTerm of agencyTerms) {
|
|
||||||
if (agencyTerm.checked)
|
|
||||||
checkedAgencyTerms.push(agencyTerm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkedAgencyTerms;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChecked() {
|
|
||||||
return this.checked.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalPrice() {
|
|
||||||
let totalPrice = 0;
|
|
||||||
|
|
||||||
if (this.checked.length > 0) {
|
|
||||||
for (let agencyTerm of this.checked)
|
|
||||||
totalPrice += agencyTerm.price;
|
|
||||||
|
|
||||||
return totalPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(route) {
|
|
||||||
this.routeSelected = route;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
createInvoiceIn() {
|
|
||||||
const rowsToCreateInvoiceIn = [];
|
|
||||||
const supplierFk = this.checked[0].supplierFk;
|
|
||||||
|
|
||||||
for (let agencyTerm of this.checked) {
|
|
||||||
let hasSameSupplier = supplierFk == agencyTerm.supplierFk;
|
|
||||||
if (hasSameSupplier) {
|
|
||||||
rowsToCreateInvoiceIn.push({
|
|
||||||
routeFk: agencyTerm.routeFk,
|
|
||||||
supplierFk: agencyTerm.supplierFk,
|
|
||||||
created: agencyTerm.created,
|
|
||||||
totalPrice: this.totalPrice});
|
|
||||||
} else {
|
|
||||||
this.vnApp.showError(this.$t('Two autonomous cannot be counted at the same time'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const params = JSON.stringify({
|
|
||||||
supplierName: this.checked[0].supplierName,
|
|
||||||
rows: rowsToCreateInvoiceIn
|
|
||||||
});
|
|
||||||
this.$state.go('route.agencyTerm.createInvoiceIn', {q: params});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAgencyTermIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,94 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('AgencyTerm', () => {
|
|
||||||
describe('Component vnAgencyTermIndex', () => {
|
|
||||||
let controller;
|
|
||||||
let $window;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$window_) => {
|
|
||||||
$window = _$window_;
|
|
||||||
const $element = angular.element('<vn-agency-term-index></vn-agency-term-index>');
|
|
||||||
controller = $componentController('vnAgencyTermIndex', {$element});
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.$.model.data = [
|
|
||||||
{supplierFk: 1, totalPrice: null},
|
|
||||||
{supplierFk: 1},
|
|
||||||
{supplierFk: 2}
|
|
||||||
];
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('checked() getter', () => {
|
|
||||||
it('should return the checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.checked;
|
|
||||||
|
|
||||||
const firstCheckedRow = checkedRows[0];
|
|
||||||
|
|
||||||
expect(firstCheckedRow.supplierFk).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('totalCheked() getter', () => {
|
|
||||||
it('should return the total checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.totalChecked;
|
|
||||||
|
|
||||||
expect(checkedRows).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('preview()', () => {
|
|
||||||
it('should show the summary dialog', () => {
|
|
||||||
controller.$.summary = {show: () => {}};
|
|
||||||
jest.spyOn(controller.$.summary, 'show');
|
|
||||||
|
|
||||||
let event = new MouseEvent('click', {
|
|
||||||
view: $window,
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true
|
|
||||||
});
|
|
||||||
const route = {id: 1};
|
|
||||||
|
|
||||||
controller.preview(event, route);
|
|
||||||
|
|
||||||
expect(controller.$.summary.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('createInvoiceIn()', () => {
|
|
||||||
it('should throw an error if more than one autonomous are checked', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
data[2].checked = true;
|
|
||||||
|
|
||||||
controller.createInvoiceIn();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the function go() on $state to go to the file management', () => {
|
|
||||||
jest.spyOn(controller.$state, 'go');
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
controller.createInvoiceIn();
|
|
||||||
|
|
||||||
delete data[0].checked;
|
|
||||||
const params = JSON.stringify({
|
|
||||||
supplierName: data[0].supplierName,
|
|
||||||
rows: [data[0]]
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith('route.agencyTerm.createInvoiceIn', {q: params});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
Agency route: Agencia ruta
|
|
||||||
Agency Agreement: Acuerdo agencia
|
|
||||||
Autonomous: Autónomos
|
|
||||||
Two autonomous cannot be counted at the same time: Dos autonónomos no pueden ser contabilizados al mismo tiempo
|
|
||||||
You cannot attach more than one document: No puedes adjuntar más de un documento
|
|
|
@ -1,96 +0,0 @@
|
||||||
<mg-ajax path="Routes/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.route"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-worker-autocomplete
|
|
||||||
ng-model="$ctrl.route.workerFk"
|
|
||||||
show-field="nickname"
|
|
||||||
vn-name="worker">
|
|
||||||
</vn-worker-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Vehicle"
|
|
||||||
ng-model="$ctrl.route.vehicleFk"
|
|
||||||
data="$ctrl.vehicles"
|
|
||||||
show-field="numberPlate"
|
|
||||||
value-field="id"
|
|
||||||
order="false"
|
|
||||||
vn-name="vehicle">
|
|
||||||
<tpl-item>{{::numberPlate}} - {{::name}}</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Created"
|
|
||||||
ng-model="$ctrl.route.created"
|
|
||||||
vn-name="created">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="$ctrl.route.agencyModeFk"
|
|
||||||
url="AgencyModes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Agency"
|
|
||||||
vn-name="agencyMode">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Km start"
|
|
||||||
ng-model="$ctrl.route.kmStart"
|
|
||||||
vn-name="kmStart"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Km end"
|
|
||||||
ng-model="$ctrl.route.kmEnd"
|
|
||||||
vn-name="kmEnd"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-time
|
|
||||||
label="Hour started"
|
|
||||||
ng-model="$ctrl.route.started"
|
|
||||||
vn-name="started">
|
|
||||||
</vn-input-time>
|
|
||||||
<vn-input-time
|
|
||||||
label="Hour finished"
|
|
||||||
ng-model="$ctrl.route.finished"
|
|
||||||
vn-name="finished">
|
|
||||||
</vn-input-time>
|
|
||||||
<vn-check
|
|
||||||
class="vn-mr-md"
|
|
||||||
label="Is served"
|
|
||||||
ng-model="$ctrl.route.isOk"
|
|
||||||
vn-name="isOk">
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textArea
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.route.description"
|
|
||||||
vn-name="description"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-textArea>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,28 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
this.$http.post(`Vehicles/sorted`, {warehouseFk: this.vnConfig.warehouseFk})
|
|
||||||
.then(res => {
|
|
||||||
this.vehicles = res.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(() =>
|
|
||||||
this.card.reload()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<'
|
|
||||||
},
|
|
||||||
require: {
|
|
||||||
card: '^vnRouteCard'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,8 +0,0 @@
|
||||||
Date finished: Fecha fin
|
|
||||||
Date started: Fecha inicio
|
|
||||||
Km start: Km de inicio
|
|
||||||
Km end: Km de fin
|
|
||||||
Description: Descripción
|
|
||||||
Hour started: Hora inicio
|
|
||||||
Hour finished: Hora fin
|
|
||||||
Is served: Se ha servido
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-route-descriptor route="$ctrl.route" card-reload="$ctrl.reload()"></vn-route-descriptor>
|
|
||||||
<vn-left-menu source="card"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,71 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import ModuleCard from 'salix/components/module-card';
|
|
||||||
|
|
||||||
class Controller extends ModuleCard {
|
|
||||||
reload() {
|
|
||||||
let filter = {
|
|
||||||
fields: [
|
|
||||||
'id',
|
|
||||||
'workerFk',
|
|
||||||
'agencyModeFk',
|
|
||||||
'created',
|
|
||||||
'm3',
|
|
||||||
'warehouseFk',
|
|
||||||
'description',
|
|
||||||
'vehicleFk',
|
|
||||||
'kmStart',
|
|
||||||
'kmEnd',
|
|
||||||
'started',
|
|
||||||
'finished',
|
|
||||||
'cost',
|
|
||||||
'zoneFk',
|
|
||||||
'isOk'
|
|
||||||
],
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'agencyMode',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'vehicle',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'm3']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'zone',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'worker',
|
|
||||||
scope: {
|
|
||||||
fields: ['id'],
|
|
||||||
include: {
|
|
||||||
relation: 'user',
|
|
||||||
scope: {
|
|
||||||
fields: ['id'],
|
|
||||||
include: {
|
|
||||||
relation: 'emailUser',
|
|
||||||
scope: {
|
|
||||||
fields: ['email']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.get(`Routes/${this.$params.id}`, {filter})
|
|
||||||
.then(res => this.route = res.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteCard', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="Routes"
|
|
||||||
data="$ctrl.route"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-worker-autocomplete
|
|
||||||
ng-model="$ctrl.route.workerFk"
|
|
||||||
show-field="nickname">
|
|
||||||
</vn-worker-autocomplete>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Created"
|
|
||||||
ng-model="$ctrl.route.created">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Vehicle"
|
|
||||||
ng-model="$ctrl.route.vehicleFk"
|
|
||||||
url="Vehicles"
|
|
||||||
show-field="numberPlate">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Agency"
|
|
||||||
ng-model="$ctrl.route.agencyModeFk"
|
|
||||||
url="AgencyModes">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.route.description"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="route.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,20 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(
|
|
||||||
res => {
|
|
||||||
this.$http.post(`Routes/${res.data.id}/updateWorkCenter`, null)
|
|
||||||
.then(() => {
|
|
||||||
this.$state.go('route.card.summary', {id: res.data.id});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,19 +1,6 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
import './main';
|
import './main';
|
||||||
import './index/';
|
|
||||||
import './search-panel';
|
|
||||||
import './descriptor';
|
import './descriptor';
|
||||||
import './descriptor-popover';
|
import './descriptor-popover';
|
||||||
import './summary';
|
import './summary';
|
||||||
import './card';
|
|
||||||
import './create';
|
|
||||||
import './basic-data';
|
|
||||||
import './log';
|
|
||||||
import './tickets';
|
|
||||||
import './agency-term/index';
|
|
||||||
import './agency-term/createInvoiceIn';
|
|
||||||
import './agency-term-search-panel';
|
|
||||||
import './ticket-popup';
|
|
||||||
import './sms';
|
|
||||||
import './roadmap';
|
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="AgencyModes"
|
|
||||||
data="agencyModes">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Vehicles"
|
|
||||||
data="vehicles">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Workers/activeWithInheritedRole"
|
|
||||||
data="activeWithInheritedRole">
|
|
||||||
</vn-crud-model>
|
|
||||||
<div class="vn-w-xl">
|
|
||||||
<vn-card>
|
|
||||||
<smart-table
|
|
||||||
model="model"
|
|
||||||
options="$ctrl.smartTableOptions"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
<slot-actions>
|
|
||||||
<section class="header">
|
|
||||||
<vn-tool-bar class="vn-mb-md">
|
|
||||||
<vn-button
|
|
||||||
icon="icon-clone"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.openClonationDialog()"
|
|
||||||
vn-tooltip="Clone selected routes">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
icon="cloud_download"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.showRouteReport()"
|
|
||||||
vn-tooltip="Download selected routes as PDF">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
icon="check"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.markAsServed()"
|
|
||||||
vn-tooltip="Mark as served">
|
|
||||||
</vn-button>
|
|
||||||
</section>
|
|
||||||
</slot-actions>
|
|
||||||
<slot-table>
|
|
||||||
<table model="model">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</th>
|
|
||||||
<th field="id" number>
|
|
||||||
<span translate>Id</span>
|
|
||||||
</th>
|
|
||||||
<th field="workerFk">
|
|
||||||
<span translate>Worker</span>
|
|
||||||
</th>
|
|
||||||
<th field="agencyName">
|
|
||||||
<span translate>Agency</span>
|
|
||||||
</th>
|
|
||||||
<th field="vehiclePlateNumber">
|
|
||||||
<span translate>Vehicle</span>
|
|
||||||
</th>
|
|
||||||
<th field="created" shrink-date>
|
|
||||||
<span translate>Date</span>
|
|
||||||
</th>
|
|
||||||
<th field="m3" number>
|
|
||||||
<span translate>m³</span>
|
|
||||||
</th>
|
|
||||||
<th field="description">
|
|
||||||
<span translate>Description</span>
|
|
||||||
</th>
|
|
||||||
<th field="started">
|
|
||||||
<span translate>Hour started</span>
|
|
||||||
</th>
|
|
||||||
<th field="finished">
|
|
||||||
<span translate>Hour finished</span>
|
|
||||||
</th>
|
|
||||||
<th shrink></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="route in model.data"
|
|
||||||
class="clickable vn-tr search-result"
|
|
||||||
ng-attr-id="{{::route.id}}" vn-droppable="$ctrl.onDrop($event)">
|
|
||||||
<td shrink>
|
|
||||||
<vn-check
|
|
||||||
ng-model="route.checked"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-check>
|
|
||||||
</td>
|
|
||||||
<td number>{{::route.id | dashIfEmpty}}</td>
|
|
||||||
<td>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="route.workerFk"
|
|
||||||
data="activeWithInheritedRole"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{firstName: $search}"
|
|
||||||
value-field="id"
|
|
||||||
where="{role: 'employee'}"
|
|
||||||
on-change="$ctrl.updateAttributes(route)"
|
|
||||||
vn-click-stop>
|
|
||||||
<tpl-item>
|
|
||||||
<div>{{name}} - {{nickname}}</div>
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="route.agencyModeFk"
|
|
||||||
data="agencyModes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
on-change="$ctrl.updateAttributes(route)"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="route.vehicleFk"
|
|
||||||
data="vehicles"
|
|
||||||
show-field="numberPlate"
|
|
||||||
value-field="id"
|
|
||||||
on-change="$ctrl.updateAttributes(route)"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td >
|
|
||||||
<td>
|
|
||||||
<vn-date-picker
|
|
||||||
ng-model="route.created"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-horizontal>
|
|
||||||
</td>
|
|
||||||
<td number>{{::route.m3 | dashIfEmpty}}</td>
|
|
||||||
<td>
|
|
||||||
<vn-textfield
|
|
||||||
ng-model="route.description"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-textfield>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-input-time
|
|
||||||
ng-model="route.started"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-input-time>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-input-time
|
|
||||||
ng-model="route.finished"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-input-time>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.showTicketPopup(route)"
|
|
||||||
vn-tooltip="Añadir tickets"
|
|
||||||
icon="icon-ticketAdd">
|
|
||||||
</vn-icon-button>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(route)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</slot-table>
|
|
||||||
</smart-table>
|
|
||||||
</vn-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-route-summary
|
|
||||||
route="$ctrl.routeSelected">
|
|
||||||
</vn-route-summary>
|
|
||||||
</vn-popup>
|
|
||||||
|
|
||||||
<vn-route-ticket-popup
|
|
||||||
vn-id="ticketPopup"
|
|
||||||
route="$ctrl.routeSelected">
|
|
||||||
</vn-route-ticket-popup>
|
|
||||||
|
|
||||||
<vn-worker-descriptor-popover
|
|
||||||
vn-id="workerDescriptor">
|
|
||||||
</vn-worker-descriptor-popover>
|
|
||||||
<vn-ticket-descriptor-popover
|
|
||||||
vn-id="ticketDescriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="clientDescriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
|
|
||||||
<div fixed-bottom-right>
|
|
||||||
<vn-vertical style="align-items: center;">
|
|
||||||
<a ui-sref="route.create" vn-bind="+">
|
|
||||||
<vn-button class="round md vn-mb-sm"
|
|
||||||
icon="add"
|
|
||||||
vn-tooltip="New route"
|
|
||||||
tooltip-position="left">
|
|
||||||
</vn-button>
|
|
||||||
</a>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Clonation dialog -->
|
|
||||||
<vn-dialog class="edit"
|
|
||||||
vn-id="clonationDialog"
|
|
||||||
on-accept="$ctrl.cloneSelectedRoutes()"
|
|
||||||
message="Select the starting date">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Starting date"
|
|
||||||
ng-model="$ctrl.createdDate">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Clone</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,151 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor($element, $, vnReport) {
|
|
||||||
super($element, $);
|
|
||||||
this.vnReport = vnReport;
|
|
||||||
this.droppableElement = 'a.vn-tr';
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(route) {
|
|
||||||
this.routeSelected = route;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
showTicketPopup(route) {
|
|
||||||
this.routeSelected = route;
|
|
||||||
this.$.ticketPopup.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
get checked() {
|
|
||||||
const rows = this.$.model.data || [];
|
|
||||||
const checkedRows = [];
|
|
||||||
for (let row of rows) {
|
|
||||||
if (row.checked)
|
|
||||||
checkedRows.push(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkedRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChecked() {
|
|
||||||
return this.checked.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
showRouteReport() {
|
|
||||||
const routesIds = [];
|
|
||||||
const access_token = this.vnToken.tokenMultimedia;
|
|
||||||
|
|
||||||
for (let route of this.checked)
|
|
||||||
routesIds.push(route.id);
|
|
||||||
const stringRoutesIds = routesIds.join(',');
|
|
||||||
|
|
||||||
if (this.checked.length <= 1) {
|
|
||||||
const url = `api/Routes/${stringRoutesIds}/driver-route-pdf?access_token=${access_token}`;
|
|
||||||
window.open(url, '_blank');
|
|
||||||
} else {
|
|
||||||
const serializedParams = this.$httpParamSerializer({
|
|
||||||
access_token,
|
|
||||||
id: stringRoutesIds
|
|
||||||
});
|
|
||||||
const url = `api/Routes/downloadZip?${serializedParams}`;
|
|
||||||
window.open(url, '_blank');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
openClonationDialog() {
|
|
||||||
this.$.clonationDialog.show();
|
|
||||||
this.createdDate = Date.vnNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
cloneSelectedRoutes() {
|
|
||||||
try {
|
|
||||||
if (!this.createdDate)
|
|
||||||
throw new Error(`The date can't be empty`);
|
|
||||||
|
|
||||||
const routesIds = [];
|
|
||||||
for (let route of this.checked)
|
|
||||||
routesIds.push(route.id);
|
|
||||||
|
|
||||||
return this.$http.post('Routes/clone', {ids: routesIds, created: this.createdDate}).then(() => {
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onDrop($event) {
|
|
||||||
const target = $event.target;
|
|
||||||
const droppable = target.closest(this.droppableElement);
|
|
||||||
const ticketId = $event.dataTransfer.getData('Text');
|
|
||||||
const routeId = droppable.id;
|
|
||||||
|
|
||||||
if (isNaN(ticketId)) {
|
|
||||||
const regexp = new RegExp(/\/ticket\/([0-9]+)\//i);
|
|
||||||
const matches = ticketId.match(regexp);
|
|
||||||
|
|
||||||
if (matches && matches.length)
|
|
||||||
this.insert(routeId, matches[1]);
|
|
||||||
else
|
|
||||||
this.vnApp.showError(this.$t('Ticket not found'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNaN(ticketId))
|
|
||||||
this.insert(routeId, ticketId);
|
|
||||||
}
|
|
||||||
|
|
||||||
insert(routeId, ticketId) {
|
|
||||||
routeId = parseInt(routeId);
|
|
||||||
ticketId = parseInt(ticketId);
|
|
||||||
|
|
||||||
const query = `Routes/${routeId}/insertTicket`;
|
|
||||||
return this.$http.patch(query, {ticketId}).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
}).catch(error => {
|
|
||||||
if (error.status == 404)
|
|
||||||
return this.vnApp.showError(this.$t('Ticket not found'));
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAttributes(route) {
|
|
||||||
if (route.started == null || route.finished == null)
|
|
||||||
return this.vnApp.showError(this.$t('You must select a valid time'));
|
|
||||||
if (route.created == null)
|
|
||||||
return this.vnApp.showError(this.$t('You must select a valid date'));
|
|
||||||
const params = {
|
|
||||||
workerFk: route.workerFk,
|
|
||||||
agencyModeFk: route.agencyModeFk,
|
|
||||||
vehicleFk: route.vehicleFk,
|
|
||||||
created: route.created,
|
|
||||||
description: route.description,
|
|
||||||
started: route.started,
|
|
||||||
finished: route.finished
|
|
||||||
};
|
|
||||||
const query = `Routes/${route.id}/`;
|
|
||||||
this.$http.patch(query, params).then(res => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
markAsServed() {
|
|
||||||
const routes = [];
|
|
||||||
for (let route of this.checked)
|
|
||||||
routes.push(route.id);
|
|
||||||
|
|
||||||
const params = {isOk: true};
|
|
||||||
for (let routeId of routes)
|
|
||||||
this.$http.patch(`Routes/${routeId}`, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnReport'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,156 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('Component vnRouteIndex', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
const $element = angular.element('<vn-route-index></vn-route-index>');
|
|
||||||
controller = $componentController('vnRouteIndex', {$element});
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.$.model.data = [{id: 1, checked: true}, {id: 2}, {id: 3}];
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('checked() getter', () => {
|
|
||||||
it('should return the checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
data[2].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.checked;
|
|
||||||
|
|
||||||
const firstCheckedRow = checkedRows[0];
|
|
||||||
const secondCheckedRow = checkedRows[1];
|
|
||||||
|
|
||||||
expect(firstCheckedRow.id).toEqual(1);
|
|
||||||
expect(secondCheckedRow.id).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('totalCheked() getter', () => {
|
|
||||||
it('should return the total checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.totalChecked;
|
|
||||||
|
|
||||||
expect(checkedRows).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('showRouteReport()', () => {
|
|
||||||
it('should call to the vnReport show method', () => {
|
|
||||||
jest.spyOn(window, 'open').mockReturnThis();
|
|
||||||
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
data[2].checked = true;
|
|
||||||
|
|
||||||
controller.showRouteReport();
|
|
||||||
|
|
||||||
expect(window.open).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('cloneSelectedRoutes()', () => {
|
|
||||||
it('should perform an http request to Routes/clone', () => {
|
|
||||||
controller.createdDate = Date.vnNew();
|
|
||||||
|
|
||||||
$httpBackend.expect('POST', 'Routes/clone').respond();
|
|
||||||
controller.cloneSelectedRoutes();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onDrop()', () => {
|
|
||||||
it('should call the insert method when dragging a ticket number', () => {
|
|
||||||
jest.spyOn(controller, 'insert');
|
|
||||||
|
|
||||||
const routeId = '1';
|
|
||||||
const expectedTicketId = '16';
|
|
||||||
const draggedElement = '16';
|
|
||||||
const droppable = document.createElement('a');
|
|
||||||
droppable.setAttribute('id', 1);
|
|
||||||
droppable.classList.add('vn-tr');
|
|
||||||
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
},
|
|
||||||
target: droppable
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.insert).toHaveBeenCalledWith(routeId, expectedTicketId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the insert method when dragging a ticket link', () => {
|
|
||||||
jest.spyOn(controller, 'insert');
|
|
||||||
|
|
||||||
const routeId = '1';
|
|
||||||
const expectedTicketId = '11';
|
|
||||||
const draggedElement = 'http://arkamcity.com/#!/ticket/11/summary';
|
|
||||||
const droppable = document.createElement('a');
|
|
||||||
droppable.setAttribute('id', 1);
|
|
||||||
droppable.classList.add('vn-tr');
|
|
||||||
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
},
|
|
||||||
target: droppable
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.insert).toHaveBeenCalledWith(routeId, expectedTicketId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error when dragging an invalid ticket link', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
const draggedElement = 'http://arkamcity.com/#!/item/11/summary';
|
|
||||||
const droppable = document.createElement('a');
|
|
||||||
droppable.setAttribute('id', 1);
|
|
||||||
droppable.classList.add('vn-tr');
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
},
|
|
||||||
target: droppable
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('Ticket not found');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('insert()', () => {
|
|
||||||
it('should perform a HTTP patch query and then call both refresh and showSuccess methods', () => {
|
|
||||||
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
const routeId = 1;
|
|
||||||
const ticketId = 11;
|
|
||||||
const data = {ticketId};
|
|
||||||
$httpBackend.expect('PATCH', `Routes/1/insertTicket`, data).respond();
|
|
||||||
controller.insert(routeId, ticketId);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('markAsServed()', () => {
|
|
||||||
it('should perform a HTTP patch query', () => {
|
|
||||||
const data = {isOk: true};
|
|
||||||
$httpBackend.expect('PATCH', `Routes/1`, data).respond();
|
|
||||||
controller.markAsServed();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
Vehicle: Vehículo
|
|
||||||
Download selected routes as PDF: Descargar rutas seleccionadas como PDF
|
|
||||||
Clone selected routes: Clonar rutas seleccionadas
|
|
||||||
The date can't be empty: La fecha no puede estar vacía
|
|
||||||
Starting date: Fecha de inicio
|
|
||||||
Hour started: Hora inicio
|
|
||||||
Hour finished: Hora fin
|
|
||||||
Go to route: Ir a la ruta
|
|
||||||
You must select a valid time: Debe seleccionar una hora válida
|
|
||||||
You must select a valid date: Debe seleccionar una fecha válida
|
|
||||||
Mark as served: Marcar como servidas
|
|
||||||
Retrieving data from the routes: Recuperando datos de las rutas
|
|
||||||
Send SMS to all clients: Mandar sms a todos los clientes de las rutas
|
|
|
@ -1 +0,0 @@
|
||||||
Unlink zone: Unlink zone {{zoneName}} from agency {{agencyName}}
|
|
|
@ -1,5 +0,0 @@
|
||||||
Routes: Rutas
|
|
||||||
Search routes by id: Buscar rutas por identificador
|
|
||||||
New route: Nueva ruta
|
|
||||||
route: ruta
|
|
||||||
Unlink zone: Desvincular zona {{zoneName}} de agencia {{agencyName}}
|
|
|
@ -1 +0,0 @@
|
||||||
<vn-log url="RouteLogs" origin-id="$ctrl.$params.id"></vn-log>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteLog', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Section,
|
|
||||||
});
|
|
|
@ -1,20 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Routes/filter"
|
|
||||||
limit="20"
|
|
||||||
order="created DESC, id DESC">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
vn-focus
|
|
||||||
panel="vn-route-search-panel"
|
|
||||||
info="Search routes by id"
|
|
||||||
fetch-params="$ctrl.fetchParams($params)"
|
|
||||||
filter="$ctrl.filterParams"
|
|
||||||
model="model">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-left-menu></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -2,36 +2,12 @@ import ngModule from '../module';
|
||||||
import ModuleMain from 'salix/components/module-main';
|
import ModuleMain from 'salix/components/module-main';
|
||||||
|
|
||||||
export default class Route extends ModuleMain {
|
export default class Route extends ModuleMain {
|
||||||
$postLink() {
|
constructor($element, $) {
|
||||||
const to = Date.vnNew();
|
super($element, $);
|
||||||
to.setDate(to.getDate() + 1);
|
|
||||||
to.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setDate(from.getDate());
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
this.filterParams = {from, to};
|
|
||||||
this.$.model.applyFilter(null, this.filterParams);
|
|
||||||
}
|
}
|
||||||
|
async $onInit() {
|
||||||
fetchParams($params) {
|
this.$state.go('home');
|
||||||
const hasEntries = Object.entries($params).length;
|
window.location.href = await this.vnApp.getUrl(`route/`);
|
||||||
if (!hasEntries)
|
|
||||||
$params.scopeDays = 1;
|
|
||||||
|
|
||||||
if (typeof $params.scopeDays === 'number') {
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const to = new Date(from.getTime());
|
|
||||||
to.setDate(to.getDate() + $params.scopeDays);
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
Object.assign($params, {from, to});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $params;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Route Component vnRoute', () => {
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject($componentController => {
|
|
||||||
let $element = angular.element(`<div></div>`);
|
|
||||||
controller = $componentController('vnRoute', {$element});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('fetchParams()', () => {
|
|
||||||
it('should return a range of dates with passed scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 2
|
|
||||||
});
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
const to = new Date(from.getTime());
|
|
||||||
to.setDate(to.getDate() + params.scopeDays);
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
const expectedParams = {
|
|
||||||
from,
|
|
||||||
scopeDays: params.scopeDays,
|
|
||||||
to
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(params).toEqual(expectedParams);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return default value for scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(params.scopeDays).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the given scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 2
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(params.scopeDays).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,98 +0,0 @@
|
||||||
<mg-ajax path="Roadmaps/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.roadmap"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield vn-focus
|
|
||||||
vn-one
|
|
||||||
label="Roadmap"
|
|
||||||
ng-model="$ctrl.roadmap.name"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="ETD date"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
vn-one
|
|
||||||
label="ETD hour"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Tractor plate"
|
|
||||||
ng-model="$ctrl.roadmap.tractorPlate"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Trailer plate"
|
|
||||||
ng-model="$ctrl.roadmap.trailerPlate"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.roadmap.supplierFk"
|
|
||||||
url="Suppliers"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
|
||||||
value-field="id"
|
|
||||||
order="nickname"
|
|
||||||
label="Carrier">
|
|
||||||
<tpl-item>
|
|
||||||
{{::id}} - {{::nickname}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Price"
|
|
||||||
ng-model="$ctrl.roadmap.price"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Driver name"
|
|
||||||
ng-model="$ctrl.roadmap.driverName"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Phone"
|
|
||||||
ng-model="$ctrl.roadmap.phone"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textArea
|
|
||||||
vn-one
|
|
||||||
label="Observations"
|
|
||||||
ng-model="$ctrl.roadmap.observations"
|
|
||||||
rule>
|
|
||||||
</vn-textArea>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,16 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-roadmap-descriptor roadmap="$ctrl.roadmap"></vn-roadmap-descriptor>
|
|
||||||
<vn-left-menu source="roadmap"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,19 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import ModuleCard from 'salix/components/module-card';
|
|
||||||
|
|
||||||
class Controller extends ModuleCard {
|
|
||||||
reload() {
|
|
||||||
const filter = {
|
|
||||||
include: [
|
|
||||||
{relation: 'supplier'}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
this.$http.get(`Roadmaps/${this.$params.id}`, {filter})
|
|
||||||
.then(res => this.roadmap = res.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmapCard', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,37 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="Roadmaps"
|
|
||||||
data="$ctrl.roadmap"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Roadmap"
|
|
||||||
ng-model="$ctrl.roadmap.name"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-date-picker
|
|
||||||
label="ETD date"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
label="ETD hour"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="roadmap.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,23 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $, $transclude, vnReport, vnEmail) {
|
|
||||||
super($element, $, $transclude);
|
|
||||||
this.roadmap = {etd: Date.vnNew()};
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(
|
|
||||||
res => this.$state.go('route.roadmap.card.summary', {id: res.data.id})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmapCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,6 +0,0 @@
|
||||||
vn-ticket-request {
|
|
||||||
.vn-textfield {
|
|
||||||
margin: 0!important;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
<vn-descriptor-content
|
|
||||||
module="route"
|
|
||||||
base-state="route.roadmap"
|
|
||||||
description="$ctrl.roadmap.name">
|
|
||||||
<slot-menu>
|
|
||||||
<vn-item
|
|
||||||
ng-click="deleteRoadmap.show()"
|
|
||||||
name="deleteRoadmap"
|
|
||||||
translate>
|
|
||||||
Delete roadmap
|
|
||||||
</vn-item>
|
|
||||||
</slot-menu>
|
|
||||||
<slot-body>
|
|
||||||
<div class="attributes">
|
|
||||||
<vn-label-value
|
|
||||||
label="Roadmap"
|
|
||||||
value="{{$ctrl.roadmap.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="ETD"
|
|
||||||
value="{{$ctrl.roadmap.etd | date:'dd/MM/yyyy HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Carrier">
|
|
||||||
<span ng-click="supplierDescriptor.show($event, $ctrl.roadmap.supplier.id)" class="link">
|
|
||||||
{{$ctrl.roadmap.supplier.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-label-value>
|
|
||||||
</div>
|
|
||||||
</slot-body>
|
|
||||||
</vn-descriptor-content>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="deleteRoadmap"
|
|
||||||
on-accept="$ctrl.onDelete()"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
message="The roadmap will be removed">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
|
@ -1,26 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Descriptor from 'salix/components/descriptor';
|
|
||||||
|
|
||||||
class Controller extends Descriptor {
|
|
||||||
get roadmap() {
|
|
||||||
return this.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
set roadmap(value) {
|
|
||||||
this.entity = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete() {
|
|
||||||
return this.$http.delete(`Roadmaps/${this.roadmap.id}`)
|
|
||||||
.then(() => this.$state.go('route.roadmap'))
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Roadmap removed')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapDescriptor', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Delete roadmap: Eliminar troncal
|
|
||||||
The roadmap will be removed: La troncal será eliminada
|
|
||||||
Roadmap removed: Troncal eliminada
|
|
|
@ -1,9 +0,0 @@
|
||||||
import './main';
|
|
||||||
import './index/';
|
|
||||||
import './summary';
|
|
||||||
import './card';
|
|
||||||
import './descriptor';
|
|
||||||
import './create';
|
|
||||||
import './basic-data';
|
|
||||||
import './search-panel';
|
|
||||||
import './stops';
|
|
|
@ -1,112 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-lg">
|
|
||||||
<vn-card class="vn-pa-md vn-w-lg">
|
|
||||||
<vn-tool-bar class="vn-ma-md">
|
|
||||||
<vn-button
|
|
||||||
disabled="$ctrl.totalChecked == 0"
|
|
||||||
ng-click="$ctrl.openClonationDialog()"
|
|
||||||
icon="icon-clone"
|
|
||||||
vn-tooltip="Clone selected roadmaps">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
disabled="$ctrl.totalChecked == 0"
|
|
||||||
ng-click="deleteRoadmaps.show()"
|
|
||||||
vn-tooltip="Delete roadmap(s)"
|
|
||||||
icon="delete">
|
|
||||||
</vn-button>
|
|
||||||
</vn-tool-bar>
|
|
||||||
<vn-table model="model">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th field="description">Roadmap</vn-th>
|
|
||||||
<vn-th field="etd" expand date>ETD</vn-th>
|
|
||||||
<vn-th field="supplierFk">Carrier</vn-th>
|
|
||||||
<vn-th field="plate">Plate</vn-th>
|
|
||||||
<vn-th field="price">Price</vn-th>
|
|
||||||
<vn-th field="observations" expand>Observations</vn-th>
|
|
||||||
<vn-th></vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<a ng-repeat="roadmap in model.data"
|
|
||||||
class="clickable vn-tr search-result"
|
|
||||||
ui-sref="route.roadmap.card.summary({id: {{::roadmap.id}}})">
|
|
||||||
<vn-td>
|
|
||||||
<vn-check
|
|
||||||
ng-model="roadmap.checked"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{::roadmap.name}}</vn-td>
|
|
||||||
<vn-td expand date>{{::roadmap.etd | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
<span
|
|
||||||
class="link"
|
|
||||||
vn-click-stop="supplierDescriptor.show($event, roadmap.supplierFk)">
|
|
||||||
{{::roadmap.supplier.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{::roadmap.tractorPlate | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td expand>{{::roadmap.price | currency: 'EUR':2 | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td expand>{{::roadmap.observations | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(roadmap)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</a>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<a
|
|
||||||
ui-sref="route.roadmap.create"
|
|
||||||
vn-tooltip="Create roadmap"
|
|
||||||
vn-bind="+"
|
|
||||||
fixed-bottom-right>
|
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
|
||||||
</a>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-roadmap-summary
|
|
||||||
roadmap="$ctrl.roadmapSelected">
|
|
||||||
</vn-roadmap-summary>
|
|
||||||
</vn-popup>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
||||||
|
|
||||||
<!-- Clonation dialog -->
|
|
||||||
<vn-dialog class="edit"
|
|
||||||
vn-id="clonationDialog"
|
|
||||||
on-accept="$ctrl.cloneSelectedRoadmaps()"
|
|
||||||
message="Select the estimated time of departure (ETD)">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="ETD"
|
|
||||||
ng-model="$ctrl.etd">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Clone</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="deleteRoadmaps"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
message="Selected roadmaps will be removed"
|
|
||||||
on-accept="$ctrl.deleteRoadmaps()">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,60 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
get checked() {
|
|
||||||
const roadmaps = this.$.model.data || [];
|
|
||||||
const checkedRoadmap = [];
|
|
||||||
for (let roadmap of roadmaps) {
|
|
||||||
if (roadmap.checked)
|
|
||||||
checkedRoadmap.push(roadmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkedRoadmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChecked() {
|
|
||||||
return this.checked.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(roadmap) {
|
|
||||||
this.roadmapSelected = roadmap;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
openClonationDialog() {
|
|
||||||
this.$.clonationDialog.show();
|
|
||||||
this.etd = Date.vnNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
cloneSelectedRoadmaps() {
|
|
||||||
try {
|
|
||||||
if (!this.etd)
|
|
||||||
throw new Error(`The date can't be empty`);
|
|
||||||
|
|
||||||
const roadmapsIds = [];
|
|
||||||
for (let roadmap of this.checked)
|
|
||||||
roadmapsIds.push(roadmap.id);
|
|
||||||
|
|
||||||
return this.$http.post('Roadmaps/clone', {ids: roadmapsIds, etd: this.etd}).then(() => {
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteRoadmaps() {
|
|
||||||
for (const roadmap of this.checked) {
|
|
||||||
this.$http.delete(`Roadmaps/${roadmap.id}`)
|
|
||||||
.then(() => this.$.model.refresh())
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Roadmaps removed')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmapIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Delete roadmap(s): Eliminar troncal(es)
|
|
||||||
Selected roadmaps will be removed: Los troncales seleccionados serán eliminados
|
|
||||||
Roadmaps removed: Troncales eliminados
|
|
|
@ -1,14 +0,0 @@
|
||||||
Roadmaps: Troncales
|
|
||||||
Roadmap: Troncal
|
|
||||||
Driver name: Nombre conductor
|
|
||||||
Plate: Matrícula
|
|
||||||
Price: Precio
|
|
||||||
Observations: Observaciones
|
|
||||||
Clone selected roadmaps: Clonar troncales seleccionadas
|
|
||||||
Select the estimated time of departure (ETD): Seleccione la hora estimada de salida (ETD)
|
|
||||||
Create roadmap: Crear troncal
|
|
||||||
Tractor plate: Matrícula tractor
|
|
||||||
Trailer plate: Matrícula trailer
|
|
||||||
Carrier: Transportista
|
|
||||||
ETD date: Fecha ETD
|
|
||||||
ETD hour: Hora ETD
|
|
|
@ -1,20 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Roadmaps"
|
|
||||||
include="$ctrl.include"
|
|
||||||
auto-load="true"
|
|
||||||
limit="20">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
info="Search roadmap by id or trunk"
|
|
||||||
panel="vn-roadmap-search-panel"
|
|
||||||
model="model"
|
|
||||||
filter="$ctrl.filterParams"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
|
||||||
base-state="route.roadmap">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view>
|
|
||||||
<vn-roadmap-index></vn-roadmap-index>
|
|
||||||
</ui-view>
|
|
|
@ -1,61 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import ModuleMain from 'salix/components/module-main';
|
|
||||||
|
|
||||||
export default class Roadmap extends ModuleMain {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
this.include = {
|
|
||||||
relation: 'supplier',
|
|
||||||
scope: {
|
|
||||||
fields: ['nickname']
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
$postLink() {
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const to = Date.vnNew();
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
this.filterParams = {
|
|
||||||
from: from,
|
|
||||||
to: to
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$.model.addFilter({where: {
|
|
||||||
and: [
|
|
||||||
{etd: {gte: from}},
|
|
||||||
{etd: {lte: to}}
|
|
||||||
]
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'search':
|
|
||||||
return /^\d+$/.test(value)
|
|
||||||
? {id: value}
|
|
||||||
: {name: {like: `%${value}%`}};
|
|
||||||
case 'from':
|
|
||||||
return {etd: {gte: value}};
|
|
||||||
case 'to':
|
|
||||||
return {etd: {lte: value}};
|
|
||||||
case 'supplierFk':
|
|
||||||
case 'price':
|
|
||||||
return {[param]: value};
|
|
||||||
case 'tractorPlate':
|
|
||||||
case 'trailerPlate':
|
|
||||||
case 'phone':
|
|
||||||
case 'driverName':
|
|
||||||
return {[param]: {like: `%${value}%`}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmap', {
|
|
||||||
controller: Roadmap,
|
|
||||||
template: require('./index.html')
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
Search roadmap by id or trunk: Buscar troncales por id o troncal
|
|
|
@ -1,74 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pt-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
info="Search routes by id"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<section class="vn-px-md">
|
|
||||||
<vn-horizontal class="manifold-panel vn-pa-md">
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="From"
|
|
||||||
ng-model="filter.from">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="To"
|
|
||||||
ng-model="filter.to">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Tractor plate"
|
|
||||||
ng-model="filter.tractorPlate">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Trailer plate"
|
|
||||||
ng-model="filter.trailerPlate">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="filter.supplierFk"
|
|
||||||
url="Suppliers"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
|
||||||
value-field="id"
|
|
||||||
order="nickname"
|
|
||||||
label="Carrier">
|
|
||||||
<tpl-item>
|
|
||||||
{{::id}} - {{::nickname}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Price"
|
|
||||||
ng-model="filter.price">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Driver name"
|
|
||||||
ng-model="filter.driverName">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Phone"
|
|
||||||
ng-model="filter.phone">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: SearchPanel
|
|
||||||
});
|
|
|
@ -1,71 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="RoadmapStops"
|
|
||||||
where="{roadmapFk: $ctrl.$params.id}"
|
|
||||||
order="eta ASC"
|
|
||||||
data="$ctrl.roadmapStops"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.roadmapStops"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form class="vn-w-md" name="form" ng-submit="$ctrl.onSubmit()">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal ng-repeat="roadmapStop in $ctrl.roadmapStops">
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="roadmapStop.warehouseFk"
|
|
||||||
url="Warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
vn-focus
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-date-picker vn-one
|
|
||||||
label="ETA date"
|
|
||||||
ng-model="roadmapStop.eta"
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
vn-one
|
|
||||||
label="ETA hour"
|
|
||||||
ng-model="roadmapStop.eta">
|
|
||||||
</vn-input-time>
|
|
||||||
<vn-textArea
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
ng-model="roadmapStop.description"
|
|
||||||
rule>
|
|
||||||
</vn-textArea>
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-tooltip="Remove stop"
|
|
||||||
icon="delete"
|
|
||||||
ng-click="model.remove($index)"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-one>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-bind="+"
|
|
||||||
vn-tooltip="Add stop"
|
|
||||||
icon="add_circle"
|
|
||||||
ng-click="$ctrl.add()">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-one>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="confirm"
|
|
||||||
question="Delete stop?"
|
|
||||||
on-accept="$ctrl.removeTicketFromRoute($index)">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,39 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
add() {
|
|
||||||
const filter = {
|
|
||||||
fields: ['etd']
|
|
||||||
};
|
|
||||||
this.$http.get(`Roadmaps/${this.$params.id}`, {filter})
|
|
||||||
.then(res => {
|
|
||||||
this.roadmap = res.data;
|
|
||||||
|
|
||||||
const eta = new Date(this.roadmap.etd);
|
|
||||||
eta.setDate(eta.getDate() + 1);
|
|
||||||
|
|
||||||
this.$.model.insert({
|
|
||||||
roadmapFk: this.$params.id,
|
|
||||||
eta: eta
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.check();
|
|
||||||
this.$.model.save().then(() => {
|
|
||||||
this.$.watcher.notifySaved();
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
this.$.model.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapStops', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,4 +0,0 @@
|
||||||
Remove stop: Eliminar parada
|
|
||||||
Add stop: Añadir parada
|
|
||||||
ETA date: Fecha ETA
|
|
||||||
ETA hour: Hora ETA
|
|
|
@ -1,116 +0,0 @@
|
||||||
<vn-card class="summary">
|
|
||||||
<h5>
|
|
||||||
<span>{{summary.id}} - {{summary.name}}</span>
|
|
||||||
</h5>
|
|
||||||
<vn-horizontal class="vn-pa-md">
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value label="Carrier">
|
|
||||||
<span ng-click="supplierDescriptor.show($event, summary.supplier.id)" class="link">
|
|
||||||
{{summary.supplier.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="ETD"
|
|
||||||
value="{{summary.etd | date:'dd/MM/yyyy HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Tractor plate"
|
|
||||||
value="{{summary.tractorPlate}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Trailer plate"
|
|
||||||
value="{{summary.trailerPlate}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value
|
|
||||||
label="Phone"
|
|
||||||
>
|
|
||||||
<vn-link-phone
|
|
||||||
phone-number="summary.phone"
|
|
||||||
></vn-link-phone>
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Worker"
|
|
||||||
value="{{summary.worker.firstName}} {{summary.worker.lastName}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Observations"
|
|
||||||
value="{{summary.observations}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-auto>
|
|
||||||
<h4>
|
|
||||||
<a
|
|
||||||
ui-sref="route.roadmap.card.stops({id:summary.id})"
|
|
||||||
target="_self">
|
|
||||||
<span translate vn-tooltip="Go to">Stops</span>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-bind="+"
|
|
||||||
vn-tooltip="Add stop"
|
|
||||||
icon="add_circle"
|
|
||||||
vn-click-stop="addRoadmapStop.show()">
|
|
||||||
</vn-icon-button>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
<vn-table model="model">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th>Wharehouse</vn-th>
|
|
||||||
<vn-th>ETA</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="roadmapStop in summary.roadmapStop">
|
|
||||||
<vn-td>{{roadmapStop.warehouse.name}}</vn-td>
|
|
||||||
<vn-td expand>{{roadmapStop.eta | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-auto>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
||||||
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="addRoadmapStop"
|
|
||||||
on-open="$ctrl.getETD()"
|
|
||||||
on-accept="$ctrl.onAddAccept()">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="$ctrl.roadmapStop.warehouseFk"
|
|
||||||
url="Warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
vn-focus
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="ETA date"
|
|
||||||
ng-model="$ctrl.roadmapStop.eta"
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
label="ETA hour"
|
|
||||||
ng-model="$ctrl.roadmapStop.eta">
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textArea
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.roadmapStop.description"
|
|
||||||
rule>
|
|
||||||
</vn-textArea>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Confirm</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,68 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Component from 'core/lib/component';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Component {
|
|
||||||
set roadmap(value) {
|
|
||||||
this._roadmap = value;
|
|
||||||
this.$.summary = null;
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
get roadmap() {
|
|
||||||
return this._roadmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadData() {
|
|
||||||
const filter = {
|
|
||||||
include: [
|
|
||||||
{relation: 'supplier'},
|
|
||||||
{relation: 'worker'},
|
|
||||||
{relation: 'roadmapStop',
|
|
||||||
scope: {
|
|
||||||
include: [
|
|
||||||
{relation: 'warehouse'}
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
this.$http.get(`Roadmaps/${this.roadmap.id}`, {filter})
|
|
||||||
.then(res => this.$.summary = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
getETD() {
|
|
||||||
const eta = new Date(this.roadmap.etd);
|
|
||||||
eta.setDate(eta.getDate() + 1);
|
|
||||||
|
|
||||||
this.roadmapStop = {eta: eta};
|
|
||||||
}
|
|
||||||
|
|
||||||
onAddAccept() {
|
|
||||||
try {
|
|
||||||
const data = {
|
|
||||||
roadmapFk: this.roadmap.id,
|
|
||||||
warehouseFk: this.roadmapStop.warehouseFk,
|
|
||||||
eta: this.roadmapStop.eta,
|
|
||||||
description: this.roadmapStop.description
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.post(`RoadmapStops`, data)
|
|
||||||
.then(() => {
|
|
||||||
this.loadData();
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapSummary', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Stops: Paradas
|
|
||||||
Wharehouse: Almacén
|
|
||||||
You must fill all the fields: Debes rellenar todos los campos
|
|
|
@ -1,9 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-roadmap-summary .summary {
|
|
||||||
a:not(vn-link-phone a) {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 18.328px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,18 +6,7 @@
|
||||||
"dependencies": ["client", "worker", "ticket", "supplier", "invoiceIn"],
|
"dependencies": ["client", "worker", "ticket", "supplier", "invoiceIn"],
|
||||||
"menus": {
|
"menus": {
|
||||||
"main": [
|
"main": [
|
||||||
{"state": "route.index", "icon": "icon-delivery"},
|
{"state": "route.index", "icon": "icon-delivery"}
|
||||||
{"state": "route.agencyTerm.index", "icon": "icon-agency-term"},
|
|
||||||
{"state": "route.roadmap", "icon": "icon-trailer"}
|
|
||||||
],
|
|
||||||
"card": [
|
|
||||||
{"state": "route.card.basicData", "icon": "settings"},
|
|
||||||
{"state": "route.card.tickets", "icon": "icon-ticket"},
|
|
||||||
{"state": "route.card.log", "icon": "history"}
|
|
||||||
],
|
|
||||||
"roadmap": [
|
|
||||||
{"state": "route.roadmap.card.basicData", "icon": "settings"},
|
|
||||||
{"state": "route.roadmap.card.stops", "icon": "icon-lines"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"routes": [
|
"routes": [
|
||||||
|
@ -33,108 +22,6 @@
|
||||||
"state": "route.index",
|
"state": "route.index",
|
||||||
"component": "vn-route-index",
|
"component": "vn-route-index",
|
||||||
"description": "Routes"
|
"description": "Routes"
|
||||||
}, {
|
|
||||||
"url": "/create",
|
|
||||||
"state": "route.create",
|
|
||||||
"component": "vn-route-create",
|
|
||||||
"description": "New route"
|
|
||||||
}, {
|
|
||||||
"url": "/:id",
|
|
||||||
"state": "route.card",
|
|
||||||
"abstract": true,
|
|
||||||
"component": "vn-route-card"
|
|
||||||
}, {
|
|
||||||
"url": "/agency-term?q",
|
|
||||||
"abstract": true,
|
|
||||||
"state": "route.agencyTerm",
|
|
||||||
"component": "ui-view"
|
|
||||||
}, {
|
|
||||||
"url": "/index",
|
|
||||||
"state": "route.agencyTerm.index",
|
|
||||||
"component": "vn-agency-term-index",
|
|
||||||
"description": "Autonomous",
|
|
||||||
"acl": ["administrative"]
|
|
||||||
},{
|
|
||||||
"url": "/createInvoiceIn?q",
|
|
||||||
"state": "route.agencyTerm.createInvoiceIn",
|
|
||||||
"component": "vn-agency-term-create-invoice-in",
|
|
||||||
"description": "File management",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
},
|
|
||||||
"acl": ["administrative"]
|
|
||||||
}, {
|
|
||||||
"url": "/summary",
|
|
||||||
"state": "route.card.summary",
|
|
||||||
"component": "vn-route-summary",
|
|
||||||
"description": "Summary",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"url": "/basic-data",
|
|
||||||
"state": "route.card.basicData",
|
|
||||||
"component": "vn-route-basic-data",
|
|
||||||
"description": "Basic data",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
},
|
|
||||||
"acl": ["delivery"]
|
|
||||||
}, {
|
|
||||||
"url" : "/log",
|
|
||||||
"state": "route.card.log",
|
|
||||||
"component": "vn-route-log",
|
|
||||||
"description": "Log",
|
|
||||||
"acl": ["delivery"]
|
|
||||||
}, {
|
|
||||||
"url": "/tickets",
|
|
||||||
"state": "route.card.tickets",
|
|
||||||
"component": "vn-route-tickets",
|
|
||||||
"description": "Tickets",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
},
|
|
||||||
"acl": ["delivery"]
|
|
||||||
}, {
|
|
||||||
"url": "/roadmap?q",
|
|
||||||
"state": "route.roadmap",
|
|
||||||
"component": "vn-roadmap",
|
|
||||||
"description": "Roadmaps"
|
|
||||||
}, {
|
|
||||||
"url": "/create",
|
|
||||||
"state": "route.roadmap.create",
|
|
||||||
"component": "vn-roadmap-create",
|
|
||||||
"description": "Create roadmap"
|
|
||||||
},{
|
|
||||||
"url": "/:id",
|
|
||||||
"state": "route.roadmap.card",
|
|
||||||
"component": "vn-roadmap-card",
|
|
||||||
"abstract": true,
|
|
||||||
"description": "Detail"
|
|
||||||
},{
|
|
||||||
"url": "/summary",
|
|
||||||
"state": "route.roadmap.card.summary",
|
|
||||||
"component": "vn-roadmap-summary",
|
|
||||||
"description": "Summary",
|
|
||||||
"params": {
|
|
||||||
"roadmap": "$ctrl.roadmap"
|
|
||||||
}
|
|
||||||
},{
|
|
||||||
"url": "/basic-data",
|
|
||||||
"state": "route.roadmap.card.basicData",
|
|
||||||
"component": "vn-roadmap-basic-data",
|
|
||||||
"description": "Basic data",
|
|
||||||
"params": {
|
|
||||||
"roadmap": "$ctrl.roadmap"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"url": "/stops",
|
|
||||||
"state": "route.roadmap.card.stops",
|
|
||||||
"component": "vn-roadmap-stops",
|
|
||||||
"description": "Stops",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.roadmap"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pt-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
info="Search routes by id"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-worker-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="filter.workerFk"
|
|
||||||
show-field="nickname">
|
|
||||||
</vn-worker-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Agency"
|
|
||||||
ng-model="filter.agencyModeFk"
|
|
||||||
url="AgencyModes/isActive"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<section class="vn-px-md">
|
|
||||||
<vn-horizontal class="manifold-panel vn-pa-md">
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="From"
|
|
||||||
ng-model="filter.from"
|
|
||||||
on-change="$ctrl.from = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="To"
|
|
||||||
ng-model="filter.to"
|
|
||||||
on-change="$ctrl.to = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-none class="or vn-px-md" translate>Or</vn-none>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
label="Days onward"
|
|
||||||
ng-model="filter.scopeDays"
|
|
||||||
on-change="$ctrl.scopeDays = value"
|
|
||||||
display-controls="true">
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-icon color-marginal
|
|
||||||
icon="info"
|
|
||||||
vn-tooltip="Cannot choose a range of dates and days onward at the same time">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Vehicle"
|
|
||||||
ng-model="filter.vehicleFk"
|
|
||||||
url="Vehicles"
|
|
||||||
show-field="numberPlate"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="m³"
|
|
||||||
ng-model="filter.m3">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="filter.warehouseFk"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
ng-model="filter.description">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,43 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
class Controller extends SearchPanel {
|
|
||||||
constructor($, $element) {
|
|
||||||
super($, $element);
|
|
||||||
this.filter = this.$.filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
get from() {
|
|
||||||
return this._from;
|
|
||||||
}
|
|
||||||
|
|
||||||
set from(value) {
|
|
||||||
this._from = value;
|
|
||||||
this.filter.scopeDays = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get to() {
|
|
||||||
return this._to;
|
|
||||||
}
|
|
||||||
|
|
||||||
set to(value) {
|
|
||||||
this._to = value;
|
|
||||||
this.filter.scopeDays = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scopeDays() {
|
|
||||||
return this._scopeDays;
|
|
||||||
}
|
|
||||||
|
|
||||||
set scopeDays(value) {
|
|
||||||
this._scopeDays = value;
|
|
||||||
|
|
||||||
this.filter.from = null;
|
|
||||||
this.filter.to = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,48 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Route Component vnRouteSearchPanel', () => {
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject($componentController => {
|
|
||||||
controller = $componentController('vnRouteSearchPanel', {$element: null});
|
|
||||||
controller.$t = () => {};
|
|
||||||
controller.filter = {};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('from() setter', () => {
|
|
||||||
it('should clear the scope days when setting the from property', () => {
|
|
||||||
controller.filter.scopeDays = 1;
|
|
||||||
|
|
||||||
controller.from = Date.vnNew();
|
|
||||||
|
|
||||||
expect(controller.filter.scopeDays).toBeNull();
|
|
||||||
expect(controller.from).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('to() setter', () => {
|
|
||||||
it('should clear the scope days when setting the to property', () => {
|
|
||||||
controller.filter.scopeDays = 1;
|
|
||||||
|
|
||||||
controller.to = Date.vnNew();
|
|
||||||
|
|
||||||
expect(controller.filter.scopeDays).toBeNull();
|
|
||||||
expect(controller.to).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('scopeDays() setter', () => {
|
|
||||||
it('should clear the date range when setting the scopeDays property', () => {
|
|
||||||
controller.filter.from = Date.vnNew();
|
|
||||||
controller.filter.to = Date.vnNew();
|
|
||||||
|
|
||||||
controller.scopeDays = 1;
|
|
||||||
|
|
||||||
expect(controller.filter.from).toBeNull();
|
|
||||||
expect(controller.filter.to).toBeNull();
|
|
||||||
expect(controller.scopeDays).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
<vn-dialog
|
|
||||||
vn-id="SMSDialog"
|
|
||||||
on-accept="$ctrl.onResponse()"
|
|
||||||
message="Send SMS to the selected tickets">
|
|
||||||
<tpl-body>
|
|
||||||
<section class="SMSDialog">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea vn-one
|
|
||||||
vn-id="message"
|
|
||||||
label="Message"
|
|
||||||
ng-model="$ctrl.sms.message"
|
|
||||||
info="Special characters like accents counts as a multiple"
|
|
||||||
rows="5"
|
|
||||||
required="true"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<span>
|
|
||||||
{{'Characters remaining' | translate}}:
|
|
||||||
<vn-chip translate-attr="{title: 'Packing'}" ng-class="{
|
|
||||||
'colored': $ctrl.charactersRemaining() > 25,
|
|
||||||
'warning': $ctrl.charactersRemaining() <= 25,
|
|
||||||
'alert': $ctrl.charactersRemaining() < 0,
|
|
||||||
}">
|
|
||||||
{{$ctrl.charactersRemaining()}}
|
|
||||||
</vn-chip>
|
|
||||||
</span>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Send</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,47 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Component from 'core/lib/component';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Component {
|
|
||||||
open() {
|
|
||||||
this.$.SMSDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
charactersRemaining() {
|
|
||||||
const element = this.$.message;
|
|
||||||
const value = element.input.value;
|
|
||||||
|
|
||||||
const maxLength = 160;
|
|
||||||
const textAreaLength = new Blob([value]).size;
|
|
||||||
return maxLength - textAreaLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
onResponse() {
|
|
||||||
try {
|
|
||||||
if (!this.sms.destination)
|
|
||||||
throw new Error(`The destination can't be empty`);
|
|
||||||
if (!this.sms.message)
|
|
||||||
throw new Error(`The message can't be empty`);
|
|
||||||
if (this.charactersRemaining() < 0)
|
|
||||||
throw new Error(`The message it's too long`);
|
|
||||||
|
|
||||||
this.$http.post(`Routes/sendSms`, this.sms).then(res => {
|
|
||||||
this.vnApp.showMessage(this.$t('SMS sent'));
|
|
||||||
|
|
||||||
if (res.data) this.emit('send', {response: res.data});
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteSms', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
sms: '<',
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,71 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Route', () => {
|
|
||||||
describe('Component vnRouteSms', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
let $scope = $rootScope.$new();
|
|
||||||
const $element = angular.element('<vn-dialog></vn-dialog>');
|
|
||||||
controller = $componentController('vnRouteSms', {$element, $scope});
|
|
||||||
controller.$.message = {
|
|
||||||
input: {
|
|
||||||
value: 'My SMS'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onResponse()', () => {
|
|
||||||
it('should perform a POST query and show a success snackbar', () => {
|
|
||||||
let params = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
|
|
||||||
controller.sms = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showMessage');
|
|
||||||
$httpBackend.expect('POST', `Routes/sendSms`, params).respond(200, params);
|
|
||||||
|
|
||||||
controller.onResponse();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onResponse without the destination and show an error snackbar', () => {
|
|
||||||
controller.sms = {destinationFk: 1101, message: 'My SMS'};
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
controller.onResponse();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith(`The destination can't be empty`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onResponse without the message and show an error snackbar', () => {
|
|
||||||
controller.sms = {destinationFk: 1101, destination: 222222222};
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
controller.onResponse();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith(`The message can't be empty`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('charactersRemaining()', () => {
|
|
||||||
it('should return the characters remaining in a element', () => {
|
|
||||||
controller.$.message = {
|
|
||||||
input: {
|
|
||||||
value: 'My message 0€'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = controller.charactersRemaining();
|
|
||||||
|
|
||||||
expect(result).toEqual(145);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
Send SMS to the selected tickets: Enviar SMS a los tickets seleccionados
|
|
||||||
Routes to notify: Rutas a notificar
|
|
||||||
Message: Mensaje
|
|
||||||
SMS sent!: ¡SMS enviado!
|
|
||||||
Characters remaining: Carácteres restantes
|
|
||||||
The destination can't be empty: El destinatario no puede estar vacio
|
|
||||||
The message can't be empty: El mensaje no puede estar vacio
|
|
||||||
The message it's too long: El mensaje es demasiado largo
|
|
||||||
Special characters like accents counts as a multiple: Carácteres especiales como los acentos cuentan como varios
|
|
|
@ -1,5 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
.SMSDialog {
|
|
||||||
min-width: 400px
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
|
|
||||||
<tpl-title>
|
|
||||||
<vn-horizontal>
|
|
||||||
<span translate>Tickets to add</span>
|
|
||||||
<div class="button-right">
|
|
||||||
<vn-button label="Add" ng-click="$ctrl.setTicketsRoute()"></vn-button>
|
|
||||||
</div>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-title>
|
|
||||||
<tpl-body id="manifold-form">
|
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Routes/{{$ctrl.route.id}}/getSuggestedTickets"
|
|
||||||
data="$ctrl.possibleTickets"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer data="$ctrl.possibleTickets" class="manifold-panel">
|
|
||||||
<vn-table auto-load="true">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th number>Ticket</vn-th>
|
|
||||||
<vn-th>Client</vn-th>
|
|
||||||
<vn-th shrink>Province</vn-th>
|
|
||||||
<vn-th shrink>
|
|
||||||
<span translate>
|
|
||||||
Population
|
|
||||||
</span>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th expand>PC</vn-th>
|
|
||||||
<vn-th>Address</vn-th>
|
|
||||||
<vn-th shrink>Zone</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="ticket in $ctrl.possibleTickets">
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-check
|
|
||||||
ng-model="ticket.checked">
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td number>
|
|
||||||
<span class="link" ng-click="ticketDescriptor.show($event, ticket.id)">
|
|
||||||
{{::ticket.id}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
<span class="link" ng-click="clientDescriptor.show($event, ticket.clientFk)">
|
|
||||||
{{::ticket.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.address.province.name}}</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.address.city}}</vn-td>
|
|
||||||
<vn-td number shrink>{{::ticket.address.postalCode}}</vn-td>
|
|
||||||
<vn-td expand title="{{::ticket.address.street}}">{{::ticket.address.street}}</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
{{::ticket.zone.name}}
|
|
||||||
<vn-icon-button
|
|
||||||
icon="link_off"
|
|
||||||
class="pointer"
|
|
||||||
title="{{'Unlink zone' | translate: {zoneName: ticket.zone.name, agencyName: ticket.agencyName} }}"
|
|
||||||
ng-click="unlinkZoneConfirmation.show(ticket)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="unlinkZoneConfirmation"
|
|
||||||
on-accept="$ctrl.unlinkZone($data)"
|
|
||||||
question="{{$ctrl.confirmationMessage}}"
|
|
||||||
message="Unlink selected zone?">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-ticket-descriptor-popover vn-id="ticket-descriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover vn-id="client-descriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
</tpl-body>
|
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Dialog from 'core/components/dialog';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Dialog {
|
|
||||||
constructor($element, $, $transclude) {
|
|
||||||
super($element, $, $transclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
getSelectedTickets(tickets) {
|
|
||||||
const selectedTickets = [];
|
|
||||||
|
|
||||||
if (tickets) {
|
|
||||||
for (let i = 0; i < tickets.length; i++) {
|
|
||||||
if (tickets[i].checked)
|
|
||||||
selectedTickets.push(tickets[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selectedTickets;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateVolume() {
|
|
||||||
let url = `Routes/${this.route.id}/updateVolume`;
|
|
||||||
this.$http.post(url).then(() => {
|
|
||||||
this.$.model.refresh();
|
|
||||||
if (this.parentReload)
|
|
||||||
this.parentReload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setTicketsRoute() {
|
|
||||||
const tickets = this.getSelectedTickets(this.possibleTickets);
|
|
||||||
if (tickets.length === 0) return;
|
|
||||||
|
|
||||||
const updates = [];
|
|
||||||
|
|
||||||
for (let ticket of tickets) {
|
|
||||||
delete ticket.checked;
|
|
||||||
const update = {
|
|
||||||
where: {id: ticket.id},
|
|
||||||
data: {routeFk: this.route.id}
|
|
||||||
};
|
|
||||||
|
|
||||||
updates.push(update);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {creates: [], updates: updates, deletes: []};
|
|
||||||
return this.$http.post(`Tickets/crud`, data)
|
|
||||||
.then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.updateVolume();
|
|
||||||
this.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
unlinkZone(ticket) {
|
|
||||||
const params = {
|
|
||||||
agencyModeId: this.route.agencyModeFk,
|
|
||||||
zoneId: ticket.zoneFk,
|
|
||||||
};
|
|
||||||
|
|
||||||
const query = `Routes/unlink`;
|
|
||||||
this.$http.post(query, params).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.$inject = ['$element', '$scope', '$transclude'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteTicketPopup', {
|
|
||||||
slotTemplate: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<',
|
|
||||||
model: '<?',
|
|
||||||
parentReload: '&'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,82 +0,0 @@
|
||||||
/* eslint max-len: ["error", { "code": 150 }]*/
|
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Route', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
let $scope;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element('<vn-route-ticket-popup></vn-route-ticket-popup>');
|
|
||||||
const $transclude = {
|
|
||||||
$$boundTransclude: {
|
|
||||||
$$slots: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
controller = $componentController('vnRouteTicketPopup', {$element, $scope, $transclude});
|
|
||||||
controller.route = {id: 1};
|
|
||||||
controller.$.model = {
|
|
||||||
refresh: () => {},
|
|
||||||
remove: () => {}
|
|
||||||
};
|
|
||||||
controller.card = {reload: () => {}};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('unlink()', () => {
|
|
||||||
it('should call the route unlink endpoint with the agency and zone ids', () => {
|
|
||||||
controller.$.model = {refresh: jest.fn()};
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
jest.spyOn(controller, 'hide');
|
|
||||||
|
|
||||||
controller.route = {
|
|
||||||
agencyModeFk: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
const ticket = {
|
|
||||||
zoneFk: 2,
|
|
||||||
};
|
|
||||||
const params = {
|
|
||||||
agencyModeId: controller.route.agencyModeFk,
|
|
||||||
zoneId: ticket.zoneFk,
|
|
||||||
};
|
|
||||||
|
|
||||||
$httpBackend.expectPOST(`Routes/unlink`, params).respond('ok');
|
|
||||||
controller.unlinkZone(ticket);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.hide).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setTicketsRoute()', () => {
|
|
||||||
it('should perform a POST query to add tickets to the route', () => {
|
|
||||||
controller.$.model = {refresh: jest.fn()};
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
jest.spyOn(controller, 'hide');
|
|
||||||
|
|
||||||
controller.route = {id: 111};
|
|
||||||
|
|
||||||
controller.possibleTickets = [
|
|
||||||
{id: 2, checked: false},
|
|
||||||
{id: 3, checked: true},
|
|
||||||
{id: 4, checked: false},
|
|
||||||
{id: 5, checked: true},
|
|
||||||
];
|
|
||||||
|
|
||||||
$httpBackend.whenPOST(`Routes/${controller.route.id}/updateVolume`).respond(200);
|
|
||||||
$httpBackend.expectPOST('Tickets/crud').respond();
|
|
||||||
controller.setTicketsRoute();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.hide).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue