Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into InvoiceOut_Migration

This commit is contained in:
Jon Elias 2024-07-31 09:52:13 +02:00
commit 1e711b63fc
155 changed files with 703 additions and 4920 deletions

View File

@ -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);

View File

@ -57,8 +57,10 @@ module.exports = Self => {
ROW_NUMBER () OVER (PARTITION BY s.id ORDER BY pickingOrder) currentItemShelving, ROW_NUMBER () OVER (PARTITION BY s.id ORDER BY pickingOrder) currentItemShelving,
COUNT(*) OVER (PARTITION BY s.id ORDER BY s.id) totalItemShelving, COUNT(*) OVER (PARTITION BY s.id ORDER BY s.id) totalItemShelving,
sh.code, sh.code,
IFNULL(p2.code, p.code) parkingCode, p2.code parkingCode,
IFNULL(p2.pickingOrder, p.pickingOrder) pickingOrder, p2.pickingOrder pickingOrder,
p.code parkingCodePrevia,
p.pickingOrder pickingOrderPrevia,
iss.id itemShelvingSaleFk, iss.id itemShelvingSaleFk,
iss.isPicked iss.isPicked
FROM ticketCollection tc FROM ticketCollection tc
@ -95,8 +97,10 @@ module.exports = Self => {
ROW_NUMBER () OVER (PARTITION BY s.id ORDER BY p.pickingOrder), ROW_NUMBER () OVER (PARTITION BY s.id ORDER BY p.pickingOrder),
COUNT(*) OVER (PARTITION BY s.id ORDER BY s.id) , COUNT(*) OVER (PARTITION BY s.id ORDER BY s.id) ,
sh.code, sh.code,
IFNULL(p2.code, p.code), p2.code,
IFNULL(p2.pickingOrder, p.pickingOrder), p2.pickingOrder,
p.code,
p.pickingOrder,
iss.id itemShelvingSaleFk, iss.id itemShelvingSaleFk,
iss.isPicked iss.isPicked
FROM sectorCollection sc FROM sectorCollection sc

View File

@ -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;

View File

@ -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,

View File

@ -11,13 +11,6 @@ module.exports = Self => {
arg: 'filter', arg: 'filter',
type: 'object', type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'}
},
{
arg: 'search',
type: 'string',
description: 'Value to filter',
http: {source: 'query'}
}, },
], ],
returns: { returns: {
@ -29,13 +22,11 @@ module.exports = Self => {
verb: 'GET', verb: 'GET',
}, },
}); });
Self.filter = async(ctx, filter, options) => { Self.filter = async(filter = {}, options) => {
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
filter = ctx?.filter ?? {};
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const where = buildFilter(filter?.where, (param, value) => { const where = buildFilter(filter?.where, (param, value) => {
switch (param) { switch (param) {
@ -50,7 +41,7 @@ module.exports = Self => {
}; };
} }
}) ?? {}; }) ?? {};
delete ctx.filter.where; delete filter.where;
const stmts = []; const stmts = [];
let stmt; let stmt;
@ -70,11 +61,13 @@ module.exports = Self => {
JOIN country c on c.id = p.countryFk JOIN country c on c.id = p.countryFk
`); `);
stmt.merge(conn.makeSuffix({where, ...ctx})); stmt.merge(conn.makeSuffix({where}));
stmt.merge(conn.makeLimit(filter));
const itemsIndex = stmts.push(stmt) - 1; const itemsIndex = stmts.push(stmt) - 1;
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions); const result = await conn.executeStmt(sql, myOptions);
return itemsIndex === 0 ? result : result[itemsIndex]; return itemsIndex === 0 ? result : result[itemsIndex];
}; };
}; };

View File

@ -6,12 +6,9 @@ describe('Postcode filter()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const ctx = { const results = await models.Postcode.filter({
filter: {
},
limit: 1 limit: 1
}; }, options);
const results = await models.Postcode.filter(ctx, options);
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
await tx.rollback(); await tx.rollback();
@ -26,14 +23,11 @@ describe('Postcode filter()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const ctx = { const results = await models.Postcode.filter({
filter: {
where: { where: {
search: 46, search: 46,
} }
}, }, options);
};
const results = await models.Postcode.filter(ctx, options);
expect(results.length).toEqual(4); expect(results.length).toEqual(4);
await tx.rollback(); await tx.rollback();
@ -48,14 +42,9 @@ describe('Postcode filter()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const ctx = { const results = await models.Postcode.filter({where: {
filter: {
where: {
search: 'Alz', search: 'Alz',
} }}, options);
},
};
const results = await models.Postcode.filter(ctx, options);
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
await tx.rollback(); await tx.rollback();
@ -70,14 +59,9 @@ describe('Postcode filter()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const ctx = { const results = await models.Postcode.filter({where: {
filter: {
where: {
search: 'one', search: 'one',
} }}, options);
},
};
const results = await models.Postcode.filter(ctx, options);
expect(results.length).toEqual(4); expect(results.length).toEqual(4);
await tx.rollback(); await tx.rollback();
@ -92,14 +76,11 @@ describe('Postcode filter()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const ctx = { const results = await models.Postcode.filter({
filter: {
where: { where: {
search: 'Ec', search: 'Ec',
} }
}, }, options);
};
const results = await models.Postcode.filter(ctx, options);
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
await tx.rollback(); await tx.rollback();

View File

@ -28,6 +28,9 @@
"Company": { "Company": {
"dataSource": "vn" "dataSource": "vn"
}, },
"Config": {
"dataSource": "vn"
},
"Continent": { "Continent": {
"dataSource": "vn" "dataSource": "vn"
}, },

22
back/models/config.json Normal file
View File

@ -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"
}
]
}

View File

@ -9,7 +9,8 @@
"properties": { "properties": {
"code": { "code": {
"id": true, "id": true,
"type": "string" "type": "string",
"required": true
} }
}, },
"relations": { "relations": {

View File

@ -12,7 +12,8 @@
"type": "number" "type": "number"
}, },
"name": { "name": {
"type": "string" "type": "string",
"required": true
} }
}, },
"relations": { "relations": {

View File

@ -2,6 +2,5 @@ apps:
- script: ./loopback/server/server.js - script: ./loopback/server/server.js
name: salix-back name: salix-back
instances: 1 instances: 1
max_restarts: 3 max_restarts: 0
restart_delay: 15000
node_args: --tls-min-v1.0 --openssl-legacy-provider node_args: --tls-min-v1.0 --openssl-legacy-provider

View File

@ -30,7 +30,7 @@ proc: BEGIN
SELECT inventoried INTO started FROM vn.config LIMIT 1; SELECT inventoried INTO started FROM vn.config LIMIT 1;
SET ended = util.VN_CURDATE(); -- TIMESTAMPADD(DAY, -1, util.VN_CURDATE()); SET ended = util.VN_CURDATE(); -- TIMESTAMPADD(DAY, -1, util.VN_CURDATE());
CALL vn.buyUltimateFromInterval(NULL, started, ended); CALL vn.buy_getUltimateFromInterval(NULL, NULL, started, ended);
DELETE FROM last_buy; DELETE FROM last_buy;

View File

@ -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 ;

View File

@ -47,7 +47,7 @@ proc: BEGIN
-- Tabla con el ultimo dia de last_buy para cada producto -- Tabla con el ultimo dia de last_buy para cada producto
-- que hace un replace de la anterior. -- que hace un replace de la anterior.
CALL buyUltimate(vWarehouseShipment, util.VN_CURDATE()); CALL buy_getUltimate (NULL, vWarehouseShipment, util.VN_CURDATE());
INSERT INTO tItemRange INSERT INTO tItemRange
SELECT t.itemFk, tr.landed SELECT t.itemFk, tr.landed

View File

@ -5,39 +5,14 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buyUltimate`(
) )
BEGIN BEGIN
/** /**
* Calcula las últimas compras realizadas hasta una fecha * @deprecated Usar buy_getUltimate
* Calcula las últimas compras realizadas hasta una fecha.
* *
* @param vItemFk Id del artículo
* @param vWarehouseFk Id del almacén * @param vWarehouseFk Id del almacén
* @param vDated Compras hasta fecha * @param vDated Compras hasta fecha
* @return tmp.buyUltimate * @return tmp.buyUltimate
*/ */
CALL cache.last_buy_refresh (FALSE); CALL buy_getUltimate(NULL, vWarehouseFk, vDated);
DROP TEMPORARY TABLE IF EXISTS tmp.buyUltimate;
CREATE TEMPORARY TABLE tmp.buyUltimate
(PRIMARY KEY (itemFk, warehouseFk),
INDEX(itemFk))
ENGINE = MEMORY
SELECT item_id itemFk, buy_id buyFk, warehouse_id warehouseFk, landing
FROM cache.last_buy
WHERE warehouse_id = vWarehouseFk OR vWarehouseFk IS NULL;
IF vDated >= util.VN_CURDATE() THEN
CALL buyUltimateFromInterval(vWarehouseFk, util.VN_CURDATE(), vDated);
REPLACE INTO tmp.buyUltimate
SELECT itemFk, buyFk, warehouseFk, landed landing
FROM tmp.buyUltimateFromInterval
WHERE (warehouseFk = vWarehouseFk OR vWarehouseFk IS NULL)
AND landed <= vDated
AND NOT isIgnored;
INSERT IGNORE INTO tmp.buyUltimate
SELECT itemFk, buyFk, warehouseFk, landed landing
FROM tmp.buyUltimateFromInterval
WHERE (warehouseFk = vWarehouseFk OR vWarehouseFk IS NULL)
AND landed > vDated
ORDER BY isIgnored = FALSE DESC;
END IF;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -6,6 +6,7 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buyUltimateFromInte
) )
BEGIN BEGIN
/** /**
* @deprecated Usar buy_getUltimateFromInterval
* Calcula las últimas compras realizadas * Calcula las últimas compras realizadas
* desde un rango de fechas. * desde un rango de fechas.
* *
@ -14,153 +15,6 @@ BEGIN
* @param vEnded Fecha fin * @param vEnded Fecha fin
* @return tmp.buyUltimateFromInterval * @return tmp.buyUltimateFromInterval
*/ */
IF vEnded IS NULL THEN CALL vn.buy_getUltimateFromInterval(NULL, vWarehouseFk, vStarted, vEnded);
SET vEnded = vStarted;
END IF;
IF vEnded < vStarted THEN
SET vStarted = TIMESTAMPADD(MONTH, -1, vEnded);
END IF;
-- Item
DROP TEMPORARY TABLE IF EXISTS tmp.buyUltimateFromInterval;
CREATE TEMPORARY TABLE tmp.buyUltimateFromInterval
(PRIMARY KEY (itemFk, warehouseFk),
INDEX(buyFk), INDEX(landed), INDEX(warehouseFk), INDEX(itemFk))
ENGINE = MEMORY
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND b.price2 > 0
ORDER BY NOT b.isIgnored DESC, t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed > vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND b.price2 > 0
AND NOT b.isIgnored
ORDER BY NOT b.isIgnored DESC, t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND b.quantity = 0
ORDER BY NOT b.isIgnored DESC, t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
-- ItemOriginal
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
itemOriginalFk,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND b.price2 > 0
AND NOT b.isIgnored
AND b.quantity > 0
AND itemOriginalFk
ORDER BY t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed > vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND b.price2 > 0
AND NOT b.isIgnored
AND itemOriginalFk
ORDER BY t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM
(SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND b.quantity = 0
AND itemOriginalFk
ORDER BY t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -0,0 +1,47 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buy_getUltimate`(
vItemFk INT,
vWarehouseFk SMALLINT,
vDated DATE
)
BEGIN
/**
* Calcula las últimas compras realizadas hasta una fecha.
*
* @param vItemFk Id del artículo
* @param vWarehouseFk Id del almacén
* @param vDated Compras hasta fecha
* @return tmp.buyUltimate
*/
CALL cache.last_buy_refresh(FALSE);
CREATE OR REPLACE TEMPORARY TABLE tmp.buyUltimate
(PRIMARY KEY (itemFk, warehouseFk),
INDEX(itemFk))
ENGINE = MEMORY
SELECT item_id itemFk, buy_id buyFk, warehouse_id warehouseFk, landing
FROM cache.last_buy
WHERE (warehouse_id = vWarehouseFk OR vWarehouseFk IS NULL)
AND (item_id = vItemFk OR vItemFk IS NULL);
IF vDated >= util.VN_CURDATE() THEN
CALL buy_getUltimateFromInterval(vItemFk, vWarehouseFk, util.VN_CURDATE(), vDated);
REPLACE INTO tmp.buyUltimate
SELECT itemFk, buyFk, warehouseFk, landed landing
FROM tmp.buyUltimateFromInterval
WHERE (warehouseFk = vWarehouseFk OR vWarehouseFk IS NULL)
AND (itemFk = vItemFk OR vItemFk IS NULL)
AND landed <= vDated
AND NOT isIgnored;
INSERT IGNORE INTO tmp.buyUltimate
SELECT itemFk, buyFk, warehouseFk, landed landing
FROM tmp.buyUltimateFromInterval
WHERE (warehouseFk = vWarehouseFk OR vWarehouseFk IS NULL)
AND (itemFk = vItemFk OR vItemFk IS NULL)
AND landed > vDated
ORDER BY isIgnored = FALSE DESC;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,175 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buy_getUltimateFromInterval`(
vItemFk INT,
vWarehouseFk SMALLINT,
vStarted DATE,
vEnded DATE
)
BEGIN
/**
* Calcula las últimas compras realizadas
* desde un rango de fechas.
*
* @param vItemFk Id del artículo
* @param vWarehouseFk Id del almacén si es NULL se actualizan todos
* @param vStarted Fecha inicial
* @param vEnded Fecha fin
* @return tmp.buyUltimateFromInterval
*/
IF vEnded IS NULL THEN
SET vEnded = vStarted;
END IF;
IF vEnded < vStarted THEN
SET vStarted = vEnded - INTERVAL 1 MONTH;
END IF;
-- Item
CREATE OR REPLACE TEMPORARY TABLE tmp.buyUltimateFromInterval
(PRIMARY KEY (itemFk, warehouseFk),
INDEX(buyFk), INDEX(landed), INDEX(warehouseFk), INDEX(itemFk))
ENGINE = MEMORY
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND (b.itemFk = vItemFk OR vItemFk IS NULL)
AND b.price2 > 0
ORDER BY NOT b.isIgnored DESC, t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed > vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND (b.itemFk = vItemFk OR vItemFk IS NULL)
AND b.price2 > 0
AND NOT b.isIgnored
ORDER BY NOT b.isIgnored DESC, t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND (b.itemFk = vItemFk OR vItemFk IS NULL)
AND b.quantity = 0
ORDER BY NOT b.isIgnored DESC, t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
-- ItemOriginal
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
itemOriginalFk,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND (b.itemFk = vItemFk OR vItemFk IS NULL)
AND b.price2 > 0
AND NOT b.isIgnored
AND b.quantity > 0
AND itemOriginalFk
ORDER BY t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM (SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed > vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND (b.itemFk = vItemFk OR vItemFk IS NULL)
AND b.price2 > 0
AND NOT b.isIgnored
AND itemOriginalFk
ORDER BY t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
INSERT IGNORE INTO tmp.buyUltimateFromInterval(itemFk, warehouseFk, buyFk, landed, isIgnored)
SELECT itemFk,
warehouseFk,
buyFk,
landed,
isIgnored
FROM
(SELECT b.itemFk,
t.warehouseInFk warehouseFk,
b.id buyFk,
t.landed,
b.isIgnored
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE t.landed BETWEEN vStarted AND vEnded
AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk)
AND (b.itemFk = vItemFk OR vItemFk IS NULL)
AND b.quantity = 0
AND itemOriginalFk
ORDER BY t.landed DESC, b.id DESC
LIMIT 10000000000000000000) sub
GROUP BY itemFk, warehouseFk;
END$$
DELIMITER ;

View File

@ -1,5 +1,9 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buy_updateGrouping`(vWarehouseFk INT, vItemFk INT, vGrouping INT) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buy_updateGrouping`(
vWarehouseFk INT,
vItemFk INT,
vGrouping INT
)
BEGIN BEGIN
/** /**
* Actualiza el grouping de las últimas compras de un artículo * Actualiza el grouping de las últimas compras de un artículo
@ -8,9 +12,9 @@ BEGIN
* @param vItemFk Id del Artículo * @param vItemFk Id del Artículo
* @param vGrouping Cantidad de grouping * @param vGrouping Cantidad de grouping
*/ */
CALL vn.buyUltimate(vWarehouseFk, util.VN_CURDATE()); CALL buy_getUltimate(vItemFk, vWarehouseFk, util.VN_CURDATE());
UPDATE vn.buy b UPDATE buy b
JOIN tmp.buyUltimate bu ON b.id = bu.buyFk JOIN tmp.buyUltimate bu ON b.id = bu.buyFk
SET b.`grouping` = vGrouping SET b.`grouping` = vGrouping
WHERE bu.warehouseFk = vWarehouseFk WHERE bu.warehouseFk = vWarehouseFk

View File

@ -8,7 +8,7 @@ BEGIN
* @param vItemFk id del item * @param vItemFk id del item
* @param vPacking packing a actualizar * @param vPacking packing a actualizar
*/ */
CALL buyUltimate(vWarehouseFk, util.VN_CURDATE()); CALL buy_getUltimate(vItemFk, vWarehouseFk, util.VN_CURDATE());
UPDATE buy b UPDATE buy b
JOIN tmp.buyUltimate bu ON b.id = bu.buyFk JOIN tmp.buyUltimate bu ON b.id = bu.buyFk

View File

@ -29,7 +29,7 @@ BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
CALL vn.zone_getShipped (vLanded, vAddressFk, vAgencyModeFk, vShowExpiredZones); CALL zone_getShipped (vLanded, vAddressFk, vAgencyModeFk, vShowExpiredZones);
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot; DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot( CREATE TEMPORARY TABLE tmp.ticketLot(
@ -74,7 +74,7 @@ BEGIN
CALL `cache`.available_refresh(vAvailableCalc, FALSE, vWarehouseFk, vShipped); CALL `cache`.available_refresh(vAvailableCalc, FALSE, vWarehouseFk, vShipped);
CALL `cache`.availableNoRaids_refresh(vAvailableNoRaidsCalc, FALSE, vWarehouseFk, vShipped); CALL `cache`.availableNoRaids_refresh(vAvailableNoRaidsCalc, FALSE, vWarehouseFk, vShipped);
CALL vn.buyUltimate(vWarehouseFk, vShipped); CALL buy_getUltimate(NULL, vWarehouseFk, vShipped);
INSERT INTO tmp.ticketLot (warehouseFk, itemFk, available, buyFk, zoneFk) INSERT INTO tmp.ticketLot (warehouseFk, itemFk, available, buyFk, zoneFk)
SELECT vWarehouseFk, SELECT vWarehouseFk,
@ -86,17 +86,17 @@ BEGIN
LEFT JOIN cache.availableNoRaids anr ON anr.item_id = a.item_id LEFT JOIN cache.availableNoRaids anr ON anr.item_id = a.item_id
AND anr.calc_id = vAvailableNoRaidsCalc AND anr.calc_id = vAvailableNoRaidsCalc
JOIN tmp.item i ON i.itemFk = a.item_id JOIN tmp.item i ON i.itemFk = a.item_id
JOIN vn.item it ON it.id = i.itemFk JOIN item it ON it.id = i.itemFk
JOIN vn.`zone` z ON z.id = vZoneFk JOIN `zone` z ON z.id = vZoneFk
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = a.item_id LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = a.item_id
LEFT JOIN edi.supplyResponse sr ON sr.ID = it.supplyResponseFk LEFT JOIN edi.supplyResponse sr ON sr.ID = it.supplyResponseFk
LEFT JOIN edi.VMPSettings v ON v.VMPID = sr.vmpID LEFT JOIN edi.VMPSettings v ON v.VMPID = sr.vmpID
LEFT JOIN edi.marketPlace mp ON mp.id = sr.MarketPlaceID LEFT JOIN edi.marketPlace mp ON mp.id = sr.MarketPlaceID
LEFT JOIN (SELECT isVNHSupplier, isEarlyBird, TRUE AS itemAllowed LEFT JOIN (SELECT isVNHSupplier, isEarlyBird, TRUE AS itemAllowed
FROM vn.addressFilter af FROM addressFilter af
JOIN (SELECT ad.provinceFk, p.countryFk, ad.isLogifloraAllowed JOIN (SELECT ad.provinceFk, p.countryFk, ad.isLogifloraAllowed
FROM vn.address ad FROM address ad
JOIN vn.province p ON p.id = ad.provinceFk JOIN province p ON p.id = ad.provinceFk
WHERE ad.id = vAddressFk WHERE ad.id = vAddressFk
) sub2 ON sub2.provinceFk <=> IFNULL(af.provinceFk, sub2.provinceFk) ) sub2 ON sub2.provinceFk <=> IFNULL(af.provinceFk, sub2.provinceFk)
AND sub2.countryFk <=> IFNULL(af.countryFk, sub2.countryFk) AND sub2.countryFk <=> IFNULL(af.countryFk, sub2.countryFk)
@ -108,18 +108,18 @@ BEGIN
OR ISNULL(af.afterDated)) OR ISNULL(af.afterDated))
) sub ON sub.isVNHSupplier = v.isVNHSupplier ) sub ON sub.isVNHSupplier = v.isVNHSupplier
AND (sub.isEarlyBird = mp.isEarlyBird OR ISNULL(sub.isEarlyBird)) AND (sub.isEarlyBird = mp.isEarlyBird OR ISNULL(sub.isEarlyBird))
JOIN vn.agencyMode am ON am.id = vAgencyModeFk JOIN agencyMode am ON am.id = vAgencyModeFk
JOIN vn.agency ag ON ag.id = am.agencyFk JOIN agency ag ON ag.id = am.agencyFk
JOIN vn.itemType itt ON itt.id = it.typeFk JOIN itemType itt ON itt.id = it.typeFk
JOIN vn.itemCategory itc on itc.id = itt.categoryFk JOIN itemCategory itc on itc.id = itt.categoryFk
JOIN vn.address ad ON ad.id = vAddressFk JOIN address ad ON ad.id = vAddressFk
LEFT JOIN vn.clientItemType cit LEFT JOIN clientItemType cit
ON cit.clientFk = ad.clientFk ON cit.clientFk = ad.clientFk
AND cit.itemTypeFk = itt.id AND cit.itemTypeFk = itt.id
LEFT JOIN vn.zoneItemType zit LEFT JOIN zoneItemType zit
ON zit.zoneFk = vZoneFk ON zit.zoneFk = vZoneFk
AND zit.itemTypeFk = itt.id AND zit.itemTypeFk = itt.id
LEFT JOIN vn.agencyModeItemType ait LEFT JOIN agencyModeItemType ait
ON ait.agencyModeFk = vAgencyModeFk ON ait.agencyModeFk = vAgencyModeFk
AND ait.itemTypeFk = itt.id AND ait.itemTypeFk = itt.id
WHERE a.calc_id = vAvailableCalc WHERE a.calc_id = vAvailableCalc
@ -133,7 +133,7 @@ BEGIN
DROP TEMPORARY TABLE tmp.buyUltimate; DROP TEMPORARY TABLE tmp.buyUltimate;
CALL vn.catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk); CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
INSERT INTO tmp.ticketCalculateItem( INSERT INTO tmp.ticketCalculateItem(
itemFk, itemFk,

View File

@ -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

View File

@ -97,7 +97,7 @@ BEGIN
FROM tmp.itemList; FROM tmp.itemList;
END IF; END IF;
CALL buyUltimateFromInterval(vWarehouseIn,vInventoryDate, vDateLanded); CALL buy_getUltimateFromInterval(NULL, vWarehouseIn,vInventoryDate, vDateLanded);
CREATE OR REPLACE TEMPORARY TABLE tTransfer CREATE OR REPLACE TEMPORARY TABLE tTransfer
ENGINE = MEMORY ENGINE = MEMORY

View File

@ -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

View File

@ -98,6 +98,7 @@ proc: BEGIN
itemShelvingFk, itemShelvingFk,
saleFk, saleFk,
quantity, quantity,
userFk,
isPicked) isPicked)
SELECT vItemShelvingFk, SELECT vItemShelvingFk,
vSaleFk, vSaleFk,

View File

@ -30,12 +30,12 @@ BEGIN
FROM itemShelvingSale iss FROM itemShelvingSale iss
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
WHERE iss.itemShelvingFk = vItemShelvingFk WHERE iss.itemShelvingFk = vItemShelvingFk
AND iss.itemFk = vItemFk AND ish.itemFk = vItemFk
AND NOT iss.isPicked AND NOT iss.isPicked
FOR UPDATE; FOR UPDATE;
INSERT INTO itemShelvingSaleReserve (saleFk, vSectorFk) INSERT INTO itemShelvingSaleReserve (saleFk, sectorFk)
SELECT DISTINCT iss.saleFk SELECT DISTINCT iss.saleFk, vSectorFk
FROM itemShelvingSale iss FROM itemShelvingSale iss
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
WHERE iss.itemShelvingFk = vItemShelvingFk WHERE iss.itemShelvingFk = vItemShelvingFk

View File

@ -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;

View File

@ -15,7 +15,7 @@ BEGIN
JOIN ticket t ON t.id = c.ticketFk JOIN ticket t ON t.id = c.ticketFk
WHERE c.id = vClaimFk; WHERE c.id = vClaimFk;
CALL buyUltimate (vWarehouseFk, util.VN_CURDATE()); CALL buy_getUltimate(NULL, vWarehouseFk, util.VN_CURDATE());
INSERT INTO itemShelving (itemFk, shelvingFk, packing, `grouping`, visible) INSERT INTO itemShelving (itemFk, shelvingFk, packing, `grouping`, visible)
SELECT s.itemFk, vShelvingFk, b.packing, b.`grouping`, cb.quantity AS visible SELECT s.itemFk, vShelvingFk, b.packing, b.`grouping`, cb.quantity AS visible

View File

@ -23,7 +23,7 @@ BEGIN
FROM operator FROM operator
WHERE workerFk = account.myUser_getId(); WHERE workerFk = account.myUser_getId();
CALL buyUltimate(vWarehouseFk, util.VN_CURDATE()); CALL buy_getUltimate(vBarcodeItem, vWarehouseFk, util.VN_CURDATE());
SELECT buyFk INTO vBuyFk SELECT buyFk INTO vBuyFk
FROM tmp.buyUltimate FROM tmp.buyUltimate

View File

@ -93,7 +93,7 @@ BEGIN
ORDER BY created DESC ORDER BY created DESC
LIMIT 1; LIMIT 1;
CALL buyUltimate(vWarehouseFk, vCurdate); CALL buy_getUltimate(vSelf, vWarehouseFk, vCurdate);
SELECT b.entryFk, bu.buyFk,IFNULL(b.buyingValue, 0) INTO vLastEntryFk, vLastBuyFk, vBuyingValueOriginal SELECT b.entryFk, bu.buyFk,IFNULL(b.buyingValue, 0) INTO vLastEntryFk, vLastBuyFk, vBuyingValueOriginal
FROM tmp.buyUltimate bu FROM tmp.buyUltimate bu

View File

@ -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,

View File

@ -1,5 +1,8 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getInfo`(IN `vBarcode` VARCHAR(22), IN `vWarehouseFk` INT) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getInfo`(
`vBarcode` VARCHAR(22),
`vWarehouseFk` INT
)
BEGIN BEGIN
/** /**
* Devuelve información relativa al item correspondiente del vBarcode pasado * Devuelve información relativa al item correspondiente del vBarcode pasado
@ -11,12 +14,14 @@ BEGIN
DECLARE vCacheAvailableFk INT; DECLARE vCacheAvailableFk INT;
DECLARE vVisibleItemShelving INT; DECLARE vVisibleItemShelving INT;
DECLARE vItemFk INT; DECLARE vItemFk INT;
DECLARE vDated DATE;
SELECT barcodeToItem(vBarcode), util.VN_CURDATE() INTO vItemFk, vDated;
CALL cache.visible_refresh(vCacheVisibleFk, FALSE, vWarehouseFk); CALL cache.visible_refresh(vCacheVisibleFk, FALSE, vWarehouseFk);
CALL cache.available_refresh(vCacheAvailableFk, FALSE, vWarehouseFk, util.VN_CURDATE()); CALL cache.available_refresh(vCacheAvailableFk, FALSE, vWarehouseFk, vDated);
CALL buyUltimate(vWarehouseFk, util.VN_CURDATE()); CALL buy_getUltimate(vItemFk, vWarehouseFk, vDated);
SELECT barcodeToItem(vBarcode) INTO vItemFk;
SELECT SUM(visible) INTO vVisibleItemShelving SELECT SUM(visible) INTO vVisibleItemShelving
FROM itemShelvingStock FROM itemShelvingStock
WHERE itemFk = vItemFk WHERE itemFk = vItemFk

View File

@ -13,7 +13,7 @@ BEGIN
*/ */
ALTER TABLE tmp.itemInventory ADD IF NOT EXISTS buy_id INT; ALTER TABLE tmp.itemInventory ADD IF NOT EXISTS buy_id INT;
CALL buyUltimate(vWarehouseFk, vDate); CALL buy_getUltimate (NULL, vWarehouseFk, vDate);
CREATE OR REPLACE TEMPORARY TABLE tmp CREATE OR REPLACE TEMPORARY TABLE tmp
(KEY (itemFk)) (KEY (itemFk))

View File

@ -204,7 +204,7 @@ BEGIN
AND (ic.id = vItemCategoryFk OR vItemCategoryFk IS NULL) AND (ic.id = vItemCategoryFk OR vItemCategoryFk IS NULL)
ON DUPLICATE KEY UPDATE tInventory.quantity = tInventory.quantity + (b.quantity); ON DUPLICATE KEY UPDATE tInventory.quantity = tInventory.quantity + (b.quantity);
CALL buyUltimate(NULL, vDateDayEnd); CALL buy_getUltimate (NULL, NULL, vDateDayEnd);
DELETE FROM tInventory WHERE quantity IS NULL OR NOT quantity; DELETE FROM tInventory WHERE quantity IS NULL OR NOT quantity;

View File

@ -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,8 +139,9 @@ 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))
ENGINE = MEMORY
SELECT it.itemFk, SELECT it.itemFk,
SUM(it.quantity) quantity, SUM(it.quantity) quantity,
im.quantity minQuantity im.quantity minQuantity
@ -152,18 +153,21 @@ proc: BEGIN
WHERE it.dated < IF(vMaxDays < 0 AND t.landing IS NOT NULL, WHERE it.dated < IF(vMaxDays < 0 AND t.landing IS NOT NULL,
t.landing, t.landing,
vDateToTomorrow) vDateToTomorrow)
GROUP BY it.itemFk GROUP BY it.itemFk;
) sub ON sub.itemFk = ai.id
SET ai.avalaible = IF(sub.minQuantity > 0, UPDATE tmp.itemInventory it
ai.avalaible, JOIN tItemAvailableCalc iac ON iac.itemFk = it.id
ai.avalaible + sub.minQuantity), SET it.avalaible = IF(iac.minQuantity > 0,
ai.sd = ai.inventory + sub.quantity; 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 ;

View File

@ -174,8 +174,9 @@ proc: BEGIN
WHERE NOT `lines`; WHERE NOT `lines`;
-- Lineas por linea de encajado -- Lineas por linea de encajado
UPDATE tmp.productionBuffer pb CREATE OR REPLACE TEMPORARY TABLE tItemPackingType
JOIN ( (PRIMARY KEY(ticketFk))
ENGINE = MEMORY
SELECT ticketFk, SELECT ticketFk,
SUM(sub.H) H, SUM(sub.H) H,
SUM(sub.V) V, SUM(sub.V) V,
@ -190,11 +191,13 @@ proc: BEGIN
JOIN item i ON i.id = s.itemFk JOIN item i ON i.id = s.itemFk
GROUP BY t.ticketFk, i.itemPackingTypeFk GROUP BY t.ticketFk, i.itemPackingTypeFk
) sub ) sub
GROUP BY ticketFk GROUP BY ticketFk;
) sub2 ON sub2.ticketFk = pb.ticketFk
SET pb.H = sub2.H, UPDATE tmp.productionBuffer pb
pb.V = sub2.V, JOIN tItemPackingType ti ON ti.ticketFk = pb.ticketFk
pb.N = sub2.N; SET pb.H = ti.H,
pb.V = ti.V,
pb.N = ti.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 ;

View File

@ -10,11 +10,6 @@ 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

View File

@ -276,7 +276,7 @@ BEGIN
ON DUPLICATE KEY UPDATE itemDelay = sub.problem, saleFk = sub.saleFk; ON DUPLICATE KEY UPDATE itemDelay = sub.problem, saleFk = sub.saleFk;
-- Redondeo: Cantidad pedida incorrecta en al grouping de la última compra -- Redondeo: Cantidad pedida incorrecta en al grouping de la última compra
CALL buyUltimate(vWarehouseFk, vDate); CALL buy_getUltimate(NULL, vWarehouseFk, vDate);
INSERT INTO tmp.sale_problems(ticketFk, hasRounding, saleFk) INSERT INTO tmp.sale_problems(ticketFk, hasRounding, saleFk)
SELECT ticketFk, problem ,saleFk SELECT ticketFk, problem ,saleFk
FROM ( FROM (

View File

@ -78,7 +78,7 @@ proc: BEGIN
DROP TEMPORARY TABLE tmp.zoneGetLanded; DROP TEMPORARY TABLE tmp.zoneGetLanded;
-- rellena la tabla buyUltimate con la ultima compra -- rellena la tabla buyUltimate con la ultima compra
CALL buyUltimate (vWarehouseFk, vShipped); CALL buy_getUltimate(NULL, vWarehouseFk, vShipped);
CREATE OR REPLACE TEMPORARY TABLE tmp.sale CREATE OR REPLACE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk)) ENGINE = MEMORY (PRIMARY KEY (saleFk)) ENGINE = MEMORY

View File

@ -53,7 +53,7 @@ BEGIN
JOIN ticket t ON t.id = s.ticketFk JOIN ticket t ON t.id = s.ticketFk
WHERE s.id = vSaleFk; WHERE s.id = vSaleFk;
CALL buyUltimate(vWarehouseFk, vDate); CALL buy_getUltimate(vNewItemFk, vWarehouseFk, vDate);
SELECT `grouping`, groupingMode, packing SELECT `grouping`, groupingMode, packing
INTO vGrouping,vGroupingMode,vPacking INTO vGrouping,vGroupingMode,vPacking
@ -61,6 +61,8 @@ BEGIN
JOIN tmp.buyUltimate tmp ON b.id = tmp.buyFk JOIN tmp.buyUltimate tmp ON b.id = tmp.buyFk
WHERE tmp.itemFk = vNewItemFk AND tmp.WarehouseFk = vWarehouseFk; WHERE tmp.itemFk = vNewItemFk AND tmp.WarehouseFk = vWarehouseFk;
DROP TEMPORARY TABLE tmp.buyUltimate;
IF vGroupingMode = 'packing' AND vPacking > 0 THEN IF vGroupingMode = 'packing' AND vPacking > 0 THEN
SET vRoundQuantity = vPacking; SET vRoundQuantity = vPacking;
END IF; END IF;

View File

@ -19,7 +19,7 @@ BEGIN
JOIN ticket t ON t.id = s.ticketFk JOIN ticket t ON t.id = s.ticketFk
WHERE s.id = vSelf; WHERE s.id = vSelf;
CALL buyUltimate(vWarehouseFk, vShipped); CALL buy_getUltimate(vItemFk, vWarehouseFk, vShipped);
CREATE OR REPLACE TEMPORARY TABLE tmp.sale CREATE OR REPLACE TEMPORARY TABLE tmp.sale
SELECT vSelf saleFk, SELECT vSelf saleFk,

View File

@ -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 ;

View File

@ -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

View File

@ -36,6 +36,6 @@ BEGIN
WHERE warehouse_id = vAuctionWarehouseFk WHERE warehouse_id = vAuctionWarehouseFk
ON DUPLICATE KEY UPDATE quantity = tmp.item.quantity + VALUES(quantity); ON DUPLICATE KEY UPDATE quantity = tmp.item.quantity + VALUES(quantity);
CALL buyUltimate(vAuctionWarehouseFk, vDated); CALL buy_getUltimate(NULL, vAuctionWarehouseFk, vDated);
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -56,13 +56,12 @@ BEGIN
FROM zone FROM zone
WHERE id = vZoneFk; WHERE id = vZoneFk;
CALL buyUltimate(vWarehouseFk, vShipped); CALL buy_getUltimate(NULL, vWarehouseFk, vShipped);
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot; DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot ENGINE = MEMORY ( CREATE TEMPORARY TABLE tmp.ticketLot ENGINE = MEMORY (
SELECT SELECT vWarehouseFk warehouseFk,
vWarehouseFk AS warehouseFk, NULL available,
NULL AS available,
s.itemFk, s.itemFk,
bu.buyFk, bu.buyFk,
vZoneFk zoneFk vZoneFk zoneFk

View File

@ -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

View File

@ -16,7 +16,7 @@ BEGIN
FROM ticket FROM ticket
WHERE id = vSelf; WHERE id = vSelf;
CALL buyUltimate(vWarehouseFk, vDated); CALL buy_getUltimate(NULL, vWarehouseFk, vDated);
CREATE OR REPLACE TEMPORARY TABLE tmp.sale CREATE OR REPLACE TEMPORARY TABLE tmp.sale
(INDEX(saleFk, isProblemCalcNeeded)) (INDEX(saleFk, isProblemCalcNeeded))

View File

@ -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;

View File

@ -1,40 +1,41 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`zone_getAddresses`( CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`zone_getAddresses`(
vSelf INT, vSelf INT,
vLanded DATE vShipped DATE,
vDepartmentFk INT
) )
BEGIN BEGIN
/** /**
* Devuelve un listado de todos los clientes activos * Devuelve un listado de todos los clientes activos
* con consignatarios a los que se les puede * con consignatarios a los que se les puede
* vender producto para esa zona y no tiene un ticket * vender producto para esa zona.
* para ese día.
* *
* @param vSelf Id de zona * @param vSelf Id de zona
* @param vDated Fecha de entrega * @param vShipped Fecha de envio
* @param vDepartmentFk Id de departamento
* @return Un select * @return Un select
*/ */
CALL zone_getPostalCode(vSelf); CALL zone_getPostalCode(vSelf);
WITH notHasTicket AS ( WITH clientWithTicket AS (
SELECT id
FROM vn.client
WHERE id NOT IN (
SELECT clientFk SELECT clientFk
FROM vn.ticket FROM vn.ticket
WHERE landed BETWEEN vLanded AND util.dayEnd(vLanded) WHERE shipped BETWEEN vShipped AND util.dayEnd(vShipped)
) )
) SELECT c.id,
SELECT c.id clientFk,
c.name, c.name,
c.phone, c.phone,
bt.description, bt.description,
c.salesPersonFk, c.salesPersonFk,
u.name username, u.name username,
aai.invoiced, aai.invoiced,
cnb.lastShipped cnb.lastShipped,
cwt.clientFk
FROM vn.client c FROM vn.client c
JOIN notHasTicket ON notHasTicket.id = c.id JOIN vn.worker w ON w.id = c.salesPersonFk
JOIN vn.workerDepartment wd ON wd.workerFk = w.id
JOIN vn.department d ON d.id = wd.departmentFk
LEFT JOIN clientWithTicket cwt ON cwt.clientFk = c.id
LEFT JOIN account.`user` u ON u.id = c.salesPersonFk LEFT JOIN account.`user` u ON u.id = c.salesPersonFk
JOIN vn.`address` a ON a.clientFk = c.id JOIN vn.`address` a ON a.clientFk = c.id
JOIN vn.postCode pc ON pc.code = a.postalCode JOIN vn.postCode pc ON pc.code = a.postalCode
@ -49,6 +50,7 @@ BEGIN
AND c.isActive AND c.isActive
AND ct.code = 'normal' AND ct.code = 'normal'
AND bt.code <> 'worker' AND bt.code <> 'worker'
AND (d.id = vDepartmentFk OR NOT vDepartmentFk)
GROUP BY c.id; GROUP BY c.id;
DROP TEMPORARY TABLE tmp.zoneNodes; DROP TEMPORARY TABLE tmp.zoneNodes;

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.invoiceInConfig
ADD dueDateMarginDays INT UNSIGNED DEFAULT 2 NULL;

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.calendar
ADD CONSTRAINT calendar_user_FK FOREIGN KEY (editorFk) REFERENCES account.`user`(id);

View File

@ -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';

View File

@ -0,0 +1,6 @@
-- Place your SQL code here
ALTER TABLE vn.itemShelvingSaleReserve DROP FOREIGN KEY IF EXISTS itemShelvingSaleReserve_sector_FK;
ALTER TABLE vn.itemShelvingSaleReserve ADD CONSTRAINT itemShelvingSaleReserve_sector_FK
FOREIGN KEY IF NOT EXISTS (sectorFk) REFERENCES vn.sector(id) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -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();
});
});

View File

@ -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);
});
});

View File

@ -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);
});
});
});

View File

@ -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);
});
});

View File

@ -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', {

View File

@ -233,5 +233,7 @@
"It has been invoiced but the PDF could not be generated": "It has been invoiced but the PDF could not be generated", "It has been invoiced but the PDF could not be generated": "It has been invoiced but the PDF could not be generated",
"It has been invoiced but the PDF of refund not be generated": "It has been invoiced but the PDF of refund not be generated", "It has been invoiced but the PDF of refund not be generated": "It has been invoiced but the PDF of refund not be generated",
"Cannot add holidays on this day": "Cannot add holidays on this day", "Cannot add holidays on this day": "Cannot add holidays on this day",
"Cannot send mail": "Cannot send mail" "Cannot send mail": "Cannot send mail",
"CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`": "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`",
"This postcode already exists": "This postcode already exists"
} }

View File

@ -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"
} }

View File

@ -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;

View File

@ -52,8 +52,8 @@ module.exports = Self => {
else { else {
const userConfig = await models.UserConfig.findById(userId, {fields: ['warehouseFk']}, myOptions); const userConfig = await models.UserConfig.findById(userId, {fields: ['warehouseFk']}, myOptions);
await Self.rawSql( await Self.rawSql(
'CALL vn.buyUltimate(?,?)', 'CALL buy_getUltimate(?, ?, ?)',
[userConfig.warehouseFk, null], [args.item, userConfig.warehouseFk, null],
myOptions myOptions
); );
let buyUltimate = await Self.rawSql( let buyUltimate = await Self.rawSql(

View File

@ -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':

View File

@ -73,7 +73,8 @@ module.exports = Self => {
}, myOptions); }, myOptions);
const travel = entry.travel(); const travel = entry.travel();
await Self.rawSql('CALL buyUltimate(?, ?)', [ await Self.rawSql('CALL buy_getUltimate(?, ?, ?)', [
null,
travel.warehouseInFk, travel.warehouseInFk,
travel.landed travel.landed
], myOptions); ], myOptions);

View File

@ -50,7 +50,8 @@ module.exports = Self => {
const stmts = []; const stmts = [];
let stmt; let stmt;
stmt = new ParameterizedSQL(`CALL buyUltimate(?, ?)`, [ stmt = new ParameterizedSQL(`CALL buy_getUltimate(?, ?, ?)`, [
null,
travel.warehouseInFk, travel.warehouseInFk,
travel.landed travel.landed
]); ]);

View File

@ -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};
} }
}); });

View File

@ -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;

View File

@ -44,16 +44,14 @@ module.exports = Self => {
]); ]);
stmts.push(stmt); stmts.push(stmt);
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.item');
stmt = new ParameterizedSQL( stmt = new ParameterizedSQL(
`CREATE TEMPORARY TABLE tmp.item `CREATE OR REPLACE TEMPORARY TABLE tmp.item
(PRIMARY KEY (itemFk)) ENGINE = MEMORY (PRIMARY KEY (itemFk)) ENGINE = MEMORY
SELECT DISTINCT SELECT DISTINCT
i.id AS itemFk, i.id itemFk,
it.id AS typeFk, it.id typeFk,
it.name, it.name,
ic.name AS categoryName ic.name categoryName
FROM tmp.availableCalc ac FROM tmp.availableCalc ac
JOIN cache.available a ON a.calc_id = ac.calcFk JOIN cache.available a ON a.calc_id = ac.calcFk
JOIN vn.item i ON i.id = a.item_id JOIN vn.item i ON i.id = a.item_id
@ -74,7 +72,7 @@ module.exports = Self => {
stmts.push(stmt); stmts.push(stmt);
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
SELECT i.typeFk AS id, i.name, i.categoryName SELECT i.typeFk id, i.name, i.categoryName
FROM tmp.item i FROM tmp.item i
JOIN tmp.ticketCalculateItem tci ON tci.itemFk = i.itemFk JOIN tmp.ticketCalculateItem tci ON tci.itemFk = i.itemFk
GROUP BY i.typeFk` GROUP BY i.typeFk`
@ -85,7 +83,6 @@ module.exports = Self => {
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
const result = await Self.rawStmt(sql, myOptions); const result = await Self.rawStmt(sql, myOptions);
return result[categoriesIndex]; return result[categoriesIndex];
}; };
}; };

View File

@ -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>

View File

@ -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
});

View File

@ -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

View File

@ -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>

View File

@ -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: '<'
}
});

View File

@ -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();
});
});
});
});

View File

@ -1,7 +0,0 @@
vn-ticket-request {
.vn-textfield {
margin: 0!important;
max-width: 100px;
}
}

View File

@ -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>

View File

@ -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
});

View File

@ -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});
});
});
});
});

View File

@ -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

View File

@ -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>

View File

@ -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'
}
});

View File

@ -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

View File

@ -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>

View File

@ -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
});

View File

@ -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>

View File

@ -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
});

View File

@ -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';

View File

@ -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></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>

View File

@ -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
});

View File

@ -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();
});
});
});

View File

@ -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

View File

@ -1 +0,0 @@
Unlink zone: Unlink zone {{zoneName}} from agency {{agencyName}}

View File

@ -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}}

View File

@ -1 +0,0 @@
<vn-log url="RouteLogs" origin-id="$ctrl.$params.id"></vn-log>

View File

@ -1,7 +0,0 @@
import ngModule from '../module';
import Section from 'salix/components/section';
ngModule.vnComponent('vnRouteLog', {
template: require('./index.html'),
controller: Section,
});

View File

@ -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>

View File

@ -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;
} }
} }

View File

@ -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);
});
});
});

View File

@ -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>

View File

@ -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: '<'
}
});

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