Merge branch 'dev' into sergiodt-patch-1
gitea/salix/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Carlos Satorres 2024-06-20 12:04:03 +00:00
commit 926982d5e0
190 changed files with 1026 additions and 5074 deletions

View File

@ -0,0 +1,72 @@
module.exports = Self => {
Self.remoteMethodCtx('acls', {
description: 'Get all of the current user acls',
returns: {
type: 'Object',
root: true
},
http: {
path: '/acls',
verb: 'GET'
}
});
const staticAcls = new Map();
const app = require('vn-loopback/server/server');
app.on('started', function() {
for (const model of app.models()) {
for (const acl of model.settings.acls) {
if (acl.principalType == 'ROLE' && acl.permission == 'ALLOW') {
const staticAcl = {
model: model.name,
property: '*',
accessType: acl.accessType,
permission: acl.permission,
principalType: acl.principalType,
principalId: acl.principalId,
};
if (staticAcls.has(acl.principalId))
staticAcls.get(acl.principalId).push(staticAcl);
else
staticAcls.set(acl.principalId, [staticAcl]);
}
}
}
});
Self.acls = async function(ctx) {
const models = Self.app.models;
const acls = [];
const userId = ctx.req.accessToken.userId;
if (userId) {
const roleMapping = await models.RoleMapping.find({
where: {
principalId: userId
},
include: [
{
relation: 'role',
scope: {
fields: [
'name'
]
}
}
]
});
const dynamicAcls = await models.ACL.find({
where: {
principalId: {
inq: roleMapping.map(rm => rm.role().name)
}
}
});
dynamicAcls.forEach(acl => acls.push(acl));
staticAcls.get('$authenticated').forEach(acl => acls.push(acl));
} else
staticAcls.get('$unauthenticated').forEach(acl => acls.push(acl));
staticAcls.get('$everyone').forEach(acl => acls.push(acl));
return acls;
};
};

View File

@ -0,0 +1,27 @@
const {models} = require('vn-loopback/server/server');
const id = {administrative: 5, employee: 1, productionBoss: 50};
describe('VnUser acls()', () => {
it('should get its owns acls', async() => {
expect(await hasAcl('administrative', id.administrative)).toBeTruthy();
expect(await hasAcl('productionBoss', id.productionBoss)).toBeTruthy();
});
it('should not get administrative acls', async() => {
expect(await hasAcl('administrative', id.employee)).toBeFalsy();
});
it('should get the $authenticated acls', async() => {
expect(await hasAcl('$authenticated', id.employee)).toBeTruthy();
});
it('should get the $everyone acls', async() => {
expect(await hasAcl('$everyone', id.employee)).toBeTruthy();
});
});
const hasAcl = async(role, userId) => {
const ctx = {req: {accessToken: {userId}, headers: {origin: 'http://localhost'}}};
const acls = await models.VnUser.acls(ctx);
return Object.values(acls).some(acl => acl.principalId === role);
};

View File

@ -12,6 +12,12 @@
"required": true, "required": true,
"id": true "id": true
}, },
"sectorFromCode": {
"type": "string"
},
"sectorToCode": {
"type": "string"
},
"backupPrinterNotificationDelay": { "backupPrinterNotificationDelay": {
"type": "string" "type": "string"
} }

View File

@ -16,6 +16,7 @@ module.exports = function(Self) {
require('../methods/vn-user/share-token')(Self); require('../methods/vn-user/share-token')(Self);
require('../methods/vn-user/update-user')(Self); require('../methods/vn-user/update-user')(Self);
require('../methods/vn-user/validate-token')(Self); require('../methods/vn-user/validate-token')(Self);
require('../methods/vn-user/acls')(Self);
Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create'); Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create');

View File

@ -140,6 +140,13 @@
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$authenticated", "principalId": "$authenticated",
"permission": "ALLOW" "permission": "ALLOW"
},
{
"property": "acls",
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
} }
], ],
"scopes": { "scopes": {

View File

@ -17,6 +17,7 @@ async function init() {
err => err ? reject(err) : resolve()); err => err ? reject(err) : resolve());
}); });
// FIXME: Workaround to wait for loopback to be ready // FIXME: Workaround to wait for loopback to be ready
app.emit('started');
await app.models.Application.status(); await app.models.Application.status();
} }

View File

@ -9,7 +9,7 @@
}, },
"vn": { "vn": {
"view": { "view": {
"expeditionPallet_Print": "06613719475fcdba8309607c38cc78efc2e348cca7bc96b48dc3ae3c12426f54" "expeditionPallet_Print": "ced2b84a114fcb99fce05f0c34f4fc03f3fa387bef92621be1bc306608a84345"
} }
} }
} }

View File

@ -1793,8 +1793,8 @@ INSERT INTO `ACL` VALUES (688,'ClientSms','create','WRITE','ALLOW','ROLE','emplo
INSERT INTO `ACL` VALUES (689,'Vehicle','sorted','WRITE','ALLOW','ROLE','employee'); INSERT INTO `ACL` VALUES (689,'Vehicle','sorted','WRITE','ALLOW','ROLE','employee');
INSERT INTO `ACL` VALUES (690,'Roadmap','*','*','ALLOW','ROLE','palletizerBoss'); INSERT INTO `ACL` VALUES (690,'Roadmap','*','*','ALLOW','ROLE','palletizerBoss');
INSERT INTO `ACL` VALUES (691,'Roadmap','*','*','ALLOW','ROLE','productionBoss'); INSERT INTO `ACL` VALUES (691,'Roadmap','*','*','ALLOW','ROLE','productionBoss');
INSERT INTO `ACL` VALUES (692,'ExpeditionTruck','*','*','ALLOW','ROLE','production'); INSERT INTO `ACL` VALUES (692,'RoadmapStop','*','*','ALLOW','ROLE','production');
INSERT INTO `ACL` VALUES (693,'ExpeditionTruck','*','*','ALLOW','ROLE','productionBoss'); INSERT INTO `ACL` VALUES (693,'RoadmapStop','*','*','ALLOW','ROLE','productionBoss');
INSERT INTO `ACL` VALUES (695,'ViaexpressConfig','internationalExpedition','WRITE','ALLOW','ROLE','employee'); INSERT INTO `ACL` VALUES (695,'ViaexpressConfig','internationalExpedition','WRITE','ALLOW','ROLE','employee');
INSERT INTO `ACL` VALUES (696,'ViaexpressConfig','renderer','READ','ALLOW','ROLE','employee'); INSERT INTO `ACL` VALUES (696,'ViaexpressConfig','renderer','READ','ALLOW','ROLE','employee');
INSERT INTO `ACL` VALUES (697,'Ticket','transferClient','WRITE','ALLOW','ROLE','administrative'); INSERT INTO `ACL` VALUES (697,'Ticket','transferClient','WRITE','ALLOW','ROLE','administrative');

View File

@ -129,7 +129,7 @@ INSERT INTO vn.itemShelving (id,itemFk,visible,shelvingFk,`grouping`,packing,pac
INSERT INTO vn.beach (code,warehouseFk) VALUES INSERT INTO vn.beach (code,warehouseFk) VALUES
('TEST',1); ('TEST',1);
INSERT INTO vn.routesMonitor (routeFk,name,beachFk,m3,expeditionTruckFk) VALUES INSERT INTO vn.routesMonitor (routeFk,name,beachFk,m3,roadmapStopFk) VALUES
(1,'TEST','TEST',1.0,1); (1,'TEST','TEST',1.0,1);
/* #5483 /* #5483
INSERT INTO vn.ticket (clientFk, warehouseFk, shipped, nickname, refFk, addressFk, workerFk, observations, isSigned, isLabeled, isPrinted, packages, location, `hour`, created, isBlocked, solution, routeFk, priority, hasPriority, companyFk, agencyModeFk, landed, isBoxed, isDeleted, zoneFk, zonePrice, zoneBonus, totalWithVat, totalWithoutVat, weight) INSERT INTO vn.ticket (clientFk, warehouseFk, shipped, nickname, refFk, addressFk, workerFk, observations, isSigned, isLabeled, isPrinted, packages, location, `hour`, created, isBlocked, solution, routeFk, priority, hasPriority, companyFk, agencyModeFk, landed, isBoxed, isDeleted, zoneFk, zonePrice, zoneBonus, totalWithVat, totalWithoutVat, weight)

View File

@ -2687,13 +2687,20 @@ INSERT INTO `vn`.`zoneAgencyMode`(`id`, `agencyModeFk`, `zoneFk`)
(3, 6, 5), (3, 6, 5),
(4, 7, 1); (4, 7, 1);
INSERT INTO `vn`.`roadmapAddress` (`addressFk`)
VALUES
(1),
(2),
(3),
(4);
INSERT INTO `vn`.`roadmap` (`id`, `name`, `tractorPlate`, `trailerPlate`, `phone`, `supplierFk`, `etd`, `observations`, `userFk`, `price`, `driverName`) INSERT INTO `vn`.`roadmap` (`id`, `name`, `tractorPlate`, `trailerPlate`, `phone`, `supplierFk`, `etd`, `observations`, `userFk`, `price`, `driverName`)
VALUES VALUES
(1, 'val-algemesi', 'RE-001', 'PO-001', '111111111', 1, util.VN_NOW(), 'this is test observation', 1, 15, 'Batman'), (1, 'val-algemesi', '1234-BCD', '9876-BCD', '111111111', 1, util.VN_NOW(), 'this is test observation', 1, 15, 'Batman'),
(2, 'alg-valencia', 'RE-002', 'PO-002', '111111111', 1, util.VN_NOW(), 'test observation', 1, 20, 'Robin'), (2, 'alg-valencia', '2345-CDF', '8765-BCD', '111111111', 1, util.VN_NOW(), 'test observation', 1, 20, 'Robin'),
(3, 'alz-algemesi', 'RE-003', 'PO-003', '222222222', 2, DATE_ADD(util.VN_NOW(), INTERVAL 2 DAY), 'observations...', 2, 25, 'Driverman'); (3, 'alz-algemesi', '3456-DFG', '7654-BCD', '222222222', 2, DATE_ADD(util.VN_NOW(), INTERVAL 2 DAY), 'observations...', 2, 25, 'Driverman');
INSERT INTO `vn`.`expeditionTruck` (`id`, `roadmapFk`, `warehouseFk`, `eta`, `description`, `userFk`) INSERT INTO `vn`.`roadmapStop` (`id`, `roadmapFk`, `addressFk`, `eta`, `description`, `userFk`)
VALUES VALUES
(1, 1, 1, DATE_ADD(util.VN_NOW(), INTERVAL 1 DAY), 'Best truck in fleet', 1), (1, 1, 1, DATE_ADD(util.VN_NOW(), INTERVAL 1 DAY), 'Best truck in fleet', 1),
(2, 1, 2, DATE_ADD(util.VN_NOW(), INTERVAL '1 2' DAY_HOUR), 'Second truck in fleet', 1), (2, 1, 2, DATE_ADD(util.VN_NOW(), INTERVAL '1 2' DAY_HOUR), 'Second truck in fleet', 1),
@ -3861,3 +3868,17 @@ INSERT INTO vn.sectorCollectionSaleGroup
SET id = 9, SET id = 9,
sectorCollectionFk = 3, sectorCollectionFk = 3,
saleGroupFk = 6; saleGroupFk = 6;
INSERT INTO `vn`.`calendarHolidays` (calendarHolidaysTypeFk, dated, calendarHolidaysNameFk, workCenterFk)
VALUES
(1, '2001-05-08', 1, 1),
(1, '2001-05-09', 1, 1),
(1, '2001-05-10', 1, 1),
(1, '2001-05-11', 1, 1),
(1, '2001-05-14', 1, 5),
(1, '2001-05-15', 1, 5),
(1, '2001-05-16', 1, 5),
(1, '2001-05-17', 1, 5),
(1, '2001-05-18', 1, 5);

View File

@ -65,11 +65,12 @@ BEGIN
JOIN vn.ticketLastState ts ON ts.ticketFk = t.id JOIN vn.ticketLastState ts ON ts.ticketFk = t.id
JOIN vn.ticketTracking tt ON tt.id = ts.ticketTrackingFk JOIN vn.ticketTracking tt ON tt.id = ts.ticketTrackingFk
JOIN vn.state st ON st.id = tt.stateFk JOIN vn.state st ON st.id = tt.stateFk
JOIN vn.alertLevel al ON al.code = 'DELIVERED'
WHERE sc.componentFk = 17 WHERE sc.componentFk = 17
AND sc.isGreuge = 0 AND sc.isGreuge = 0
AND t.shipped >= '2016-10-01' AND t.shipped >= '2016-10-01'
AND t.shipped < util.VN_CURDATE() AND t.shipped < util.VN_CURDATE()
AND st.alertLevel >= 3; AND st.alertLevel >= al.id;
DELETE g.* DELETE g.*
FROM vn.greuge g FROM vn.greuge g

View File

@ -46,7 +46,7 @@ BEGIN
JOIN vn.address a ON a.id = t.addressFk JOIN vn.address a ON a.id = t.addressFk
JOIN vn.province p ON p.id = a.provinceFk JOIN vn.province p ON p.id = a.provinceFk
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk
LEFT JOIN vn.roadmapStop rs ON rs.id = rm.expeditionTruckFk LEFT JOIN vn.roadmapStop rs ON rs.id = rm.roadmapStopFk
LEFT JOIN vn.beach b ON b.code = rm.beachFk LEFT JOIN vn.beach b ON b.code = rm.beachFk
LEFT JOIN vn.`zone`z ON z.id = t.zoneFk LEFT JOIN vn.`zone`z ON z.id = t.zoneFk
JOIN vn.agencyMode am ON t.agencyModeFk = am.id JOIN vn.agencyMode am ON t.agencyModeFk = am.id

View File

@ -74,9 +74,10 @@ BEGIN
FROM vn.sale m FROM vn.sale m
JOIN vn.ticket t ON t.id = m.ticketFk JOIN vn.ticket t ON t.id = m.ticketFk
JOIN vn.ticketState s ON s.ticketFk = t.id JOIN vn.ticketState s ON s.ticketFk = t.id
JOIN vn.alertLevel al ON al.code = 'DELIVERED'
WHERE t.shipped BETWEEN vDateInv AND util.VN_CURDATE() WHERE t.shipped BETWEEN vDateInv AND util.VN_CURDATE()
AND t.warehouseFk = vWarehouse AND t.warehouseFk = vWarehouse
AND s.alertLevel = 3 AND s.alertLevel = al.id
) t ) t
GROUP BY itemFk GROUP BY itemFk
HAVING quantity > 0; HAVING quantity > 0;

View File

@ -121,6 +121,7 @@ BEGIN
) )
SELECT t.id INTO vTicket SELECT t.id INTO vTicket
FROM vn.ticket t FROM vn.ticket t
JOIN vn.alertLevel al ON al.code = 'FREE'
LEFT JOIN tPrevia tp ON tp.ticketFk = t.id LEFT JOIN tPrevia tp ON tp.ticketFk = t.id
LEFT JOIN vn.ticketState tls on tls.ticketFk = t.id LEFT JOIN vn.ticketState tls on tls.ticketFk = t.id
JOIN hedera.`order` o JOIN hedera.`order` o
@ -131,7 +132,7 @@ BEGIN
WHERE o.id = vSelf WHERE o.id = vSelf
AND t.refFk IS NULL AND t.refFk IS NULL
AND tp.ticketFk IS NULL AND tp.ticketFk IS NULL
AND IFNULL(tls.alertLevel,0) = 0 AND (tls.alertLevel IS NULL OR tls.alertLevel = al.id)
LIMIT 1; LIMIT 1;
-- Crea el ticket en el caso de no existir uno adecuado -- Crea el ticket en el caso de no existir uno adecuado

View File

@ -22,7 +22,7 @@ BEGIN
LEFT JOIN vn.route r ON r.id = t.routeFk LEFT JOIN vn.route r ON r.id = t.routeFk
LEFT JOIN vn.agencyMode am ON am.id = r.agencyModeFk LEFT JOIN vn.agencyMode am ON am.id = r.agencyModeFk
LEFT JOIN vn.routesMonitor rm ON t.routeFk = rm.routeFk LEFT JOIN vn.routesMonitor rm ON t.routeFk = rm.routeFk
LEFT JOIN vn.roadmapStop rs ON rm.expeditionTruckFk = rs.id LEFT JOIN vn.roadmapStop rs ON rm.roadmapStopFk = rs.id
WHERE e.id = vExpeditionFk; WHERE e.id = vExpeditionFk;
RETURN vDayMinute; RETURN vDayMinute;

View File

@ -34,7 +34,7 @@ FROM (
) )
LEFT JOIN `vn`.`routesMonitor` `rm` ON(`t`.`routeFk` = `rm`.`routeFk`) LEFT JOIN `vn`.`routesMonitor` `rm` ON(`t`.`routeFk` = `rm`.`routeFk`)
) )
LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rm`.`expeditionTruckFk` = `rs`.`id`) LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rm`.`roadmapStopFk` = `rs`.`id`)
) )
LEFT JOIN `vn`.`zone` `z` ON(`z`.`id` = `t`.`zoneFk`) LEFT JOIN `vn`.`zone` `z` ON(`z`.`id` = `t`.`zoneFk`)
) )

View File

@ -45,7 +45,7 @@ FROM (
) )
LEFT JOIN `vn`.`routesMonitor` `rm` ON(`t`.`routeFk` = `rm`.`routeFk`) LEFT JOIN `vn`.`routesMonitor` `rm` ON(`t`.`routeFk` = `rm`.`routeFk`)
) )
LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rm`.`expeditionTruckFk` = `rs`.`id`) LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rm`.`roadmapStopFk` = `rs`.`id`)
) )
JOIN `srt`.`config` `c` JOIN `srt`.`config` `c`
) )

View File

@ -32,7 +32,7 @@ FROM (
) )
LEFT JOIN `vn`.`routesMonitor` `rm` ON(`t`.`routeFk` = `rm`.`routeFk`) LEFT JOIN `vn`.`routesMonitor` `rm` ON(`t`.`routeFk` = `rm`.`routeFk`)
) )
LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rm`.`expeditionTruckFk` = `rs`.`id`) LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rm`.`roadmapStopFk` = `rs`.`id`)
) )
JOIN `dipole`.`expedition_PrintOut` `epo` ON(`epo`.`expeditionFk` = `e`.`id`) JOIN `dipole`.`expedition_PrintOut` `epo` ON(`epo`.`expeditionFk` = `e`.`id`)
) )

View File

@ -16,12 +16,13 @@ BEGIN
m.created, m.created,
TIMESTAMPADD(DAY, tp.life, t.shipped) expired, TIMESTAMPADD(DAY, tp.life, t.shipped) expired,
m.quantity < 0 isIn, m.quantity < 0 isIn,
m.isPicked OR s.alertLevel > 1 isPicked m.isPicked OR s.alertLevel > al.id isPicked
FROM vn.sale m FROM vn.sale m
JOIN vn.ticket t ON t.id = m.ticketFk JOIN vn.ticket t ON t.id = m.ticketFk
JOIN vn.ticketState s ON s.ticketFk = t.id JOIN vn.ticketState s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = m.itemFk JOIN vn.item i ON i.id = m.itemFk
JOIN vn.itemType tp ON tp.id = i.typeFk JOIN vn.itemType tp ON tp.id = i.typeFk
JOIN vn.alertLevel al ON al.code = 'ON_PREPARATION'
WHERE ( WHERE (
vTableId IS NULL vTableId IS NULL
OR (vTableName = 'ticket' AND t.id = vTableId) OR (vTableName = 'ticket' AND t.id = vTableId)

View File

@ -1,5 +1,7 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buy_afterUpsert`(vSelf INT) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`buy_afterUpsert`(
vSelf INT
)
BEGIN BEGIN
/** /**
* Triggered actions when a buy is updated or inserted. * Triggered actions when a buy is updated or inserted.
@ -47,6 +49,9 @@ BEGIN
WHERE e.id = vEntryFk; WHERE e.id = vEntryFk;
IF vIsMerchandise THEN IF vIsMerchandise THEN
IF vWarehouse IS NULL THEN
CALL util.throw('The entry does not have travel');
END IF;
REPLACE itemCost SET REPLACE itemCost SET
itemFk = vItemFk, itemFk = vItemFk,

View File

@ -34,7 +34,7 @@ BEGIN
LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk
LEFT JOIN vn.agency a ON a.id = am.agencyFk LEFT JOIN vn.agency a ON a.id = am.agencyFk
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk
LEFT JOIN vn.roadmapStop rs ON rs.id = rm.expeditionTruckFk LEFT JOIN vn.roadmapStop rs ON rs.id = rm.roadmapStopFk
JOIN vn.packagingConfig pc JOIN vn.packagingConfig pc
WHERE t.warehouseFk IN (60,1,44) WHERE t.warehouseFk IN (60,1,44)
AND e.created BETWEEN vStarted AND vEnded AND e.created BETWEEN vStarted AND vEnded

View File

@ -56,13 +56,13 @@ BEGIN
LIMIT 1; LIMIT 1;
IF vPalletFk IS NULL THEN IF vPalletFk IS NULL THEN
SELECT expeditionTruckFk SELECT roadmapStopFk
INTO vTruckFk INTO vTruckFk
FROM ( FROM (
SELECT rm.expeditionTruckFk, count(*) n SELECT rm.roadmapStopFk, count(*) n
FROM vn.routesMonitor rm FROM vn.routesMonitor rm
JOIN tExpedition e ON e.routeFk = rm.routeFk JOIN tExpedition e ON e.routeFk = rm.routeFk
GROUP BY expeditionTruckFk GROUP BY roadmapStopFk
ORDER BY n DESC ORDER BY n DESC
LIMIT 1) sub; LIMIT 1) sub;

View File

@ -1,9 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`expeditionTruck_Add`(vHour VARCHAR(5), vDescription VARCHAR(45))
BEGIN
INSERT INTO vn.roadmapStop(eta,description)
VALUES(CONCAT(util.VN_CURDATE(), ' ', vHour), vDescription);
END$$
DELIMITER ;

View File

@ -1,12 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`expeditionTruck_List`()
BEGIN
SELECT id truckFk,
eta,
description Destino
FROM roadmapStop
WHERE eta BETWEEN util.VN_CURDATE() AND util.dayend(util.VN_CURDATE())
ORDER BY eta;
END$$
DELIMITER ;

View File

@ -67,7 +67,7 @@ BEGIN
LEFT JOIN vn.route r ON r.id = t.routeFk LEFT JOIN vn.route r ON r.id = t.routeFk
LEFT JOIN vn.agencyMode am ON am.id = r.agencyModeFk LEFT JOIN vn.agencyMode am ON am.id = r.agencyModeFk
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = r.id LEFT JOIN vn.routesMonitor rm ON rm.routeFk = r.id
LEFT JOIN vn.roadmapStop rs ON rs.id = rm.expeditionTruckFk LEFT JOIN vn.roadmapStop rs ON rs.id = rm.roadmapStopFk
WHERE e.id = vExpeditionFk; WHERE e.id = vExpeditionFk;
END$$ END$$

View File

@ -15,7 +15,8 @@ BEGIN
t.addressFk, t.addressFk,
a.nickname, a.nickname,
sub2.itemPackingTypeConcat, sub2.itemPackingTypeConcat,
est.code est.code,
es.isScanned
FROM expedition e FROM expedition e
JOIN ticket t ON t.id = e.ticketFk JOIN ticket t ON t.id = e.ticketFk
JOIN ticketState ts ON ts.ticketFk = e.ticketFk JOIN ticketState ts ON ts.ticketFk = e.ticketFk
@ -33,6 +34,10 @@ BEGIN
GROUP BY sub.ticketFk GROUP BY sub.ticketFk
) sub2 ON sub2.ticketFk = t.id ) sub2 ON sub2.ticketFk = t.id
LEFT JOIN expeditionStateType est ON est.id = e.stateTypeFk LEFT JOIN expeditionStateType est ON est.id = e.stateTypeFk
LEFT JOIN expeditionState es ON es.id = (
SELECT MAX(id)
FROM expeditionState es
WHERE expeditionFk = e.id)
WHERE t.routeFk = vRouteFk AND e.freightItemFk <> FALSE WHERE t.routeFk = vRouteFk AND e.freightItemFk <> FALSE
ORDER BY r.created, t.priority DESC; ORDER BY r.created, t.priority DESC;
END$$ END$$

View File

@ -50,7 +50,7 @@ BEGIN
LEFT JOIN vn.route r ON r.id = t.routeFk LEFT JOIN vn.route r ON r.id = t.routeFk
LEFT JOIN vn.agencyMode am ON am.id = r.agencyModeFk LEFT JOIN vn.agencyMode am ON am.id = r.agencyModeFk
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = r.id LEFT JOIN vn.routesMonitor rm ON rm.routeFk = r.id
LEFT JOIN vn.roadmapStop rs ON rs.id = rm.expeditionTruckFk LEFT JOIN vn.roadmapStop rs ON rs.id = rm.roadmapStopFk
WHERE e.id = vExpeditionFk; WHERE e.id = vExpeditionFk;
END$$ END$$

View File

@ -153,7 +153,9 @@ BEGIN
FROM tmp.ticketToInvoice ti FROM tmp.ticketToInvoice ti
LEFT JOIN ticketState ts ON ti.id = ts.ticketFk LEFT JOIN ticketState ts ON ti.id = ts.ticketFk
JOIN state s JOIN state s
WHERE IFNULL(ts.alertLevel, 0) < 3 and s.`code` = getAlert3State(ti.id); JOIN alertLevel al ON al.code = 'DELIVERED'
WHERE (ts.alertLevel IS NULL OR ts.alertLevel < al.id)
AND s.`code` = getAlert3State(ti.id);
INSERT INTO ticketTracking(stateFk, ticketFk, userFk) INSERT INTO ticketTracking(stateFk, ticketFk, userFk)
SELECT * FROM tmp.updateInter; SELECT * FROM tmp.updateInter;

View File

@ -49,7 +49,7 @@ BEGIN
ish.isChecked, ish.isChecked,
sub.isAllChecked sub.isAllChecked
FROM itemShelvingStock iss FROM itemShelvingStock iss
JOIN itemShelving ish ON ish.shelvingFk = iss.shelvingFk JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
LEFT JOIN ( LEFT JOIN (
SELECT itemFk, SELECT itemFk,
IF( IF(

View File

@ -6,14 +6,16 @@ BEGIN
(PRIMARY KEY (ticketFk)) (PRIMARY KEY (ticketFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT t.id ticketFk, t.clientFk SELECT t.id ticketFk, t.clientFk
FROM vn.ticket t FROM ticket t
LEFT JOIN vn.ticketState ts ON ts.ticketFk = t.id JOIN alertLevel al ON al.code = 'DELIVERED'
JOIN vn.client c ON c.id = t.clientFk LEFT JOIN ticketState ts ON ts.ticketFk = t.id
JOIN client c ON c.id = t.clientFk
WHERE c.typeFk IN ('normal','handMaking','internalUse') WHERE c.typeFk IN ('normal','handMaking','internalUse')
AND ( AND (
t.shipped BETWEEN util.VN_CURDATE() AND vEndingDate t.shipped BETWEEN util.VN_CURDATE() AND vEndingDate
OR ( OR (
ts.alertLevel < 3 ts.alertLevel < al.id
AND t.shipped >= vStartingDate AND t.shipped >= vStartingDate
AND t.shipped < util.VN_CURDATE() AND t.shipped < util.VN_CURDATE()
) )

View File

@ -67,7 +67,7 @@ proc: BEGIN
wk.code salesPersonCode, wk.code salesPersonCode,
p.id provinceFk, p.id provinceFk,
tls.productionOrder, tls.productionOrder,
IFNULL(tls.alertLevel, 0) alertLevel, IFNULL(tls.alertLevel, al.id) alertLevel,
t.isBoxed palletized, t.isBoxed palletized,
IF(rm.isPickingAllowed, rm.bufferFk, NULL) ubicacion, IF(rm.isPickingAllowed, rm.bufferFk, NULL) ubicacion,
tlu.lastUpdated, tlu.lastUpdated,
@ -81,6 +81,7 @@ proc: BEGIN
rm.bufferFk rm.bufferFk
FROM tmp.productionTicket tt FROM tmp.productionTicket tt
JOIN ticket t ON tt.ticketFk = t.id JOIN ticket t ON tt.ticketFk = t.id
JOIN alertLevel al ON al.code = 'FREE'
LEFT JOIN ticketStateToday tst ON tst.ticketFk = t.id LEFT JOIN ticketStateToday tst ON tst.ticketFk = t.id
LEFT JOIN `state` st ON st.id = tst.state LEFT JOIN `state` st ON st.id = tst.state
LEFT JOIN client c ON c.id = t.clientFk LEFT JOIN client c ON c.id = t.clientFk

View File

@ -47,7 +47,7 @@ BEGIN
LEFT JOIN ticketTrolley tt ON tt.ticket = t.id LEFT JOIN ticketTrolley tt ON tt.ticket = t.id
LEFT JOIN zone zo ON t.zoneFk = zo.id LEFT JOIN zone zo ON t.zoneFk = zo.id
LEFT JOIN routesMonitor rm ON rm.routeFk = t.routeFk LEFT JOIN routesMonitor rm ON rm.routeFk = t.routeFk
LEFT JOIN roadmapStop rs ON rs.id = rm.expeditionTruckFk LEFT JOIN roadmapStop rs ON rs.id = rm.roadmapStopFk
WHERE IF(vIsCollection, tc.collectionFk = vParam, tc.ticketFk = vParam) WHERE IF(vIsCollection, tc.collectionFk = vParam, tc.ticketFk = vParam)
GROUP BY t.id GROUP BY t.id
ORDER BY cc.code; ORDER BY cc.code;

View File

@ -106,7 +106,7 @@ BEGIN
SET rm.m3boxes = sub.m3boxes; SET rm.m3boxes = sub.m3boxes;
UPDATE routesMonitor rm UPDATE routesMonitor rm
JOIN vn.roadmapStop rs ON rs.id = rm.expeditionTruckFk JOIN vn.roadmapStop rs ON rs.id = rm.roadmapStopFk
SET rm.etd = rs.eta; SET rm.etd = rs.eta;
DROP TEMPORARY TABLE tmp.routesMonitor; DROP TEMPORARY TABLE tmp.routesMonitor;

View File

@ -5,10 +5,10 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`supplierPackaging_R
) )
BEGIN BEGIN
/** /**
* Selecciona los embalajes de un proveedor a partir de una fecha * Create a report with packaging balance
* *
* @param vFromDated Fecha de la que partir * @param vFromDated Starting date
* @param vSupplierFk Id del proveedor * @param vSupplierFk Supplier ID
*/ */
SET @vBalance = 0; SET @vBalance = 0;
SET @vItemFk = NULL; SET @vItemFk = NULL;
@ -99,6 +99,7 @@ BEGIN
WHERE su.id = vSupplierFk WHERE su.id = vSupplierFk
AND t.shipped < vFromDated AND t.shipped < vFromDated
AND p.isPackageReturnable AND p.isPackageReturnable
AND NOT t.isDeleted
GROUP BY s.itemFk GROUP BY s.itemFk
UNION ALL UNION ALL
SELECT vSupplierFk, SELECT vSupplierFk,
@ -138,8 +139,9 @@ BEGIN
JOIN client c ON c.id = t.clientFk JOIN client c ON c.id = t.clientFk
JOIN supplier su ON su.nif = c.fi JOIN supplier su ON su.nif = c.fi
WHERE su.id = vSupplierFk WHERE su.id = vSupplierFk
AND t.shipped >= vFromDated AND t.shipped < vFromDated
AND p.isPackageReturnable AND p.isPackageReturnable
AND NOT t.isDeleted
GROUP BY p.itemFk GROUP BY p.itemFk
ORDER BY itemFk, landed, entryFk ORDER BY itemFk, landed, entryFk
) sub ) sub

View File

@ -7,13 +7,16 @@ BEGIN
DECLARE vShipped DATE; DECLARE vShipped DATE;
DECLARE vWarehouse TINYINT; DECLARE vWarehouse TINYINT;
DECLARE vAlertLevel INT; DECLARE vAlertLevel INT;
DECLARE vAlertLevelFree INT;
SELECT t.warehouseFk, t.shipped, ts.alertLevel INTO vWarehouse, vShipped, vAlertLevel SELECT t.warehouseFk, t.shipped, ts.alertLevel, al.id
INTO vWarehouse, vShipped, vAlertLevel, vAlertLevelFree
FROM ticket t FROM ticket t
JOIN alertLevel al ON al.code = 'FREE'
LEFT JOIN ticketState ts ON ts.ticketFk = vTicket LEFT JOIN ticketState ts ON ts.ticketFk = vTicket
WHERE t.id = vTicket; WHERE t.id = vTicket;
IF vAlertLevel IS NULL OR vAlertLevel = 0 THEN IF vAlertLevel IS NULL OR vAlertLevel = vAlertLevelFree THEN
IF vShipped >= util.VN_CURDATE() THEN IF vShipped >= util.VN_CURDATE() THEN
CALL cache.available_refresh(vAvailableCalc, FALSE, vWarehouse, vShipped); CALL cache.available_refresh(vAvailableCalc, FALSE, vWarehouse, vShipped);
END IF; END IF;

View File

@ -1,49 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticketMissed_List`(vTicketFk INT)
BEGIN
DECLARE vParkingFk INT;
DECLARE vParked DATETIME;
DECLARE vLevel INT;
DECLARE vCollectionFk INT;
SELECT IFNULL(`level`,0), IFNULL(collectionFk,0)
INTO vLevel, vCollectionFk
FROM vn.ticketCollection
WHERE ticketFk = vTicketFk
LIMIT 1;
SELECT created, parkingFk
INTO vParked, vParkingFk
FROM vn.ticketParking
WHERE ticketFk = vTicketFk;
SELECT tp.ticketFk, CONCAT(tc.collectionFk, ' - ', tc.level) coleccion, tp.created, p.code, am.name as Agencia
FROM vn.ticketParking tp
JOIN vn.parking p ON p.id = tp.parkingFk
JOIN vn.sector sc ON sc.id = p.sectorFk
LEFT JOIN vn.ticketCollection tc ON tc.ticketFk = tp.ticketFk
JOIN vn.ticketStateToday tst ON tst.ticketFk = tp.ticketFk
JOIN vn.ticket t ON t.id = tp.ticketFk
JOIN vn.zone z ON z.id = t.zoneFk
JOIN vn.agencyMode am ON am.id = z.agencyModeFk
JOIN vn.state s ON s.id = tst.state
WHERE (s.alertLevel < 2
AND tp.parkingFk = vParkingFk
AND sc.isPackagingArea
AND (
(
( IFNULL(tc.collectionFk,-1) != IFNULL(@vCollectionFk,0) AND tp.created < vParked )
OR
( tc.collectionFk = vCollectionFk AND LEFT(tc.level,1) < LEFT(vLevel,1) )
)
)) -- Etiquetas que no se han escaneado y ya estamos con una posterior
OR
(s.alertLevel > 1
AND tp.parkingFk = vParkingFk
AND sc.isPackagingArea
AND tp.created < vParked
AND t.packages <=> 0);
END$$
DELIMITER ;

View File

@ -42,7 +42,9 @@ BEGIN
JOIN vn.zone z ON z.id = t.zoneFk JOIN vn.zone z ON z.id = t.zoneFk
JOIN vn.agencyMode am ON am.id = z.agencyModeFk JOIN vn.agencyMode am ON am.id = z.agencyModeFk
JOIN vn.state s ON s.id = tst.state JOIN vn.state s ON s.id = tst.state
WHERE (s.alertLevel < 2 JOIN vn.alertLevel alPacked ON alPacked.code = 'PACKED'
JOIN vn.alertLevel alOnPreparation ON alOnPreparation.code = 'ON_PREPARATION'
WHERE (s.alertLevel < alPacked.id
AND tp.parkingFk = vParkingFk AND tp.parkingFk = vParkingFk
AND sc.isPackagingArea AND sc.isPackagingArea
AND ( AND (
@ -55,7 +57,7 @@ BEGIN
) )
) -- Etiquetas que no se han escaneado y ya estamos con una posterior ) -- Etiquetas que no se han escaneado y ya estamos con una posterior
OR OR
(s.alertLevel > 1 (s.alertLevel > alOnPreparation.id
AND tp.parkingFk = vParkingFk AND tp.parkingFk = vParkingFk
AND sc.isPackagingArea AND sc.isPackagingArea
AND tp.created < vParked AND tp.created < vParked

View File

@ -10,14 +10,17 @@ BEGIN
*/ */
DECLARE vAlertLevel INT; DECLARE vAlertLevel INT;
DECLARE vAlertLevelPacked INT;
SELECT s.alertLevel INTO vAlertLevel SELECT s.alertLevel, al.id
INTO vAlertLevel, vAlertLevelPacked
FROM state s FROM state s
JOIN ticketStateToday tst ON tst.state = s.id JOIN ticketStateToday tst ON tst.state = s.id
JOIN alertLevel al ON al.code = 'PACKED'
WHERE tst.ticketFk = vTicketFk WHERE tst.ticketFk = vTicketFk
LIMIT 1; LIMIT 1;
IF vAlertLevel < 2 THEN IF vAlertLevel < vAlertLevelPacked THEN
CALL vn.ticket_setState(vTicketFk, vStateCode); CALL vn.ticket_setState(vTicketFk, vStateCode);

View File

@ -1,26 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticketStateUpdate`(vTicketFk INT, vStateCode VARCHAR(45))
BEGIN
/*
* @deprecated:utilizar ticket_setState
*/
DECLARE vAlertLevel INT;
SELECT s.alertLevel INTO vAlertLevel
FROM vn.state s
JOIN vn.ticketState ts ON ts.stateFk = s.id
WHERE ts.ticketFk = vTicketFk;
IF !(vStateCode = 'ON_CHECKING' AND vAlertLevel > 1) THEN
INSERT INTO ticketTracking(stateFk, ticketFk, userFk)
SELECT id, vTicketFk, account.myUser_getId()
FROM vn.state
WHERE `code` = vStateCode collate utf8_unicode_ci;
END IF;
END$$
DELIMITER ;

View File

@ -13,10 +13,11 @@ BEGIN
CREATE TEMPORARY TABLE tmp.ticket CREATE TEMPORARY TABLE tmp.ticket
SELECT ticketFk SELECT ticketFk
FROM tmp.productionBuffer FROM tmp.productionBuffer
JOIN alertLevel al ON al.code = 'FREE'
WHERE shipped = util.VN_CURDATE() WHERE shipped = util.VN_CURDATE()
AND problem LIKE '%I:%' AND problem LIKE '%I:%'
AND (HH <= vHour OR HH = vHour AND mm < vMinute) AND (HH <= vHour OR HH = vHour AND mm < vMinute)
AND alertLevel = 0; AND alertLevel = al.id;
OPEN cur1; OPEN cur1;

View File

@ -18,7 +18,7 @@ BEGIN
com.id companyFk, com.id companyFk,
a.id addressFk, a.id addressFk,
c2.defaultAddressFk, c2.defaultAddressFk,
su.id supplierFk, IFNULL(sat.supplierFk, su.id) supplierFk,
t.landed t.landed
FROM ticket t FROM ticket t
JOIN ticketState ts ON ts.ticketFk = t.id JOIN ticketState ts ON ts.ticketFk = t.id
@ -28,7 +28,6 @@ BEGIN
JOIN `address` a ON a.id = t.addressFk JOIN `address` a ON a.id = t.addressFk
JOIN province p ON p.id = a.provinceFk JOIN province p ON p.id = a.provinceFk
JOIN country co ON co.id = p.countryFk JOIN country co ON co.id = p.countryFk
JOIN agencyMode am ON am.id = t.agencyModeFk
JOIN warehouse w ON w.id = t.warehouseFk JOIN warehouse w ON w.id = t.warehouseFk
JOIN company com ON com.id = t.companyFk JOIN company com ON com.id = t.companyFk
JOIN client c2 ON c2.id = com.clientFk JOIN client c2 ON c2.id = com.clientFk
@ -37,6 +36,10 @@ BEGIN
LEFT JOIN route r ON r.id = t.routeFk LEFT JOIN route r ON r.id = t.routeFk
LEFT JOIN worker wo ON wo.id = r.workerFk LEFT JOIN worker wo ON wo.id = r.workerFk
LEFT JOIN vehicle v ON v.id = r.vehicleFk LEFT JOIN vehicle v ON v.id = r.vehicleFk
LEFT JOIN agencyMode am ON am.id = r.agencyModeFk
LEFT JOIN agency ag ON ag.id = am.agencyFk
LEFT JOIN supplierAgencyTerm sat ON sat.agencyFk = ag.id
AND wo.isFreelance
WHERE al.code IN ('PACKED', 'DELIVERED') WHERE al.code IN ('PACKED', 'DELIVERED')
AND co.code <> 'ES' AND co.code <> 'ES'
AND am.name <> 'ABONO' AND am.name <> 'ABONO'

View File

@ -0,0 +1,11 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`claimRatio_afterInsert`
AFTER INSERT ON `claimRatio`
FOR EACH ROW
BEGIN
INSERT INTO clientRate(clientFk, `value`)
VALUES(NEW.clientFk, NEW.priceIncreasing)
ON DUPLICATE KEY UPDATE
`value` = VALUES(`value`);
END$$
DELIMITER ;

View File

@ -0,0 +1,11 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`claimRatio_afterUpdate`
AFTER UPDATE ON `claimRatio`
FOR EACH ROW
BEGIN
INSERT INTO clientRate(clientFk, `value`)
VALUES(NEW.clientFk, NEW.priceIncreasing)
ON DUPLICATE KEY UPDATE
`value` = VALUES(`value`);
END$$
DELIMITER ;

View File

@ -0,0 +1,8 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`clientUnpaid_beforeInsert`
BEFORE INSERT ON `clientUnpaid`
FOR EACH ROW
BEGIN
SET NEW.editorFk = account.myUser_getId();
END$$
DELIMITER ;

View File

@ -0,0 +1,8 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`clientUnpaid_beforeUpdate`
BEFORE UPDATE ON `clientUnpaid`
FOR EACH ROW
BEGIN
SET NEW.editorFk = account.myUser_getId();
END$$
DELIMITER ;

View File

@ -1,13 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`deviceProductionConfig_afterUpdate`
AFTER UPDATE ON `deviceProductionConfig`
FOR EACH ROW
BEGIN
IF NEW.isAllUsersAllowed = 1 OR NEW.isAllUsersAllowed = -1 THEN
SET @username := (SELECT account.myUser_getName());
INSERT INTO vn.mail (receiver, subject, body)
VALUES ('cau@verdnatura.es', 'Se ha activado la autenticación sin restricciones en la app',
CONCAT('El usuario ', @username,' ha habilitado la opción para que todos los usuarios puedan acceder a la app sin restricciones'));
END IF;
END$$
DELIMITER ;

View File

@ -3,8 +3,7 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`expedition_beforeInse
BEFORE INSERT ON `expedition` BEFORE INSERT ON `expedition`
FOR EACH ROW FOR EACH ROW
BEGIN BEGIN
DECLARE intcounter INT; DECLARE vMaxCounter INT;
DECLARE vShipFk INT;
SET NEW.editorFk = account.myUser_getId(); SET NEW.editorFk = account.myUser_getId();
@ -12,16 +11,17 @@ BEGIN
UPDATE ticket SET packages = IFNULL(packages, 0) + 1 WHERE id = NEW.ticketFk; UPDATE ticket SET packages = IFNULL(packages, 0) + 1 WHERE id = NEW.ticketFk;
SELECT IFNULL(MAX(counter),0) +1 INTO intcounter SELECT IFNULL(MAX(counter),0) + 1 INTO vMaxCounter
FROM expedition e FROM expedition e
INNER JOIN ticket t1 ON e.ticketFk = t1.id JOIN alertLevel al ON al.code = 'DELIVERED'
JOIN ticket t1 ON e.ticketFk = t1.id
LEFT JOIN ticketState ts ON ts.ticketFk = t1.id LEFT JOIN ticketState ts ON ts.ticketFk = t1.id
INNER JOIN ticket t2 ON t2.addressFk = t1.addressFk AND DATE(t2.shipped) = DATE(t1.shipped) JOIN ticket t2 ON t2.addressFk = t1.addressFk AND DATE(t2.shipped) = DATE(t1.shipped)
AND t1.warehouseFk = t2.warehouseFk AND t1.warehouseFk = t2.warehouseFk
WHERE t2.id = NEW.ticketFk AND ts.alertLevel < 3 AND t1.companyFk = t2.companyFk WHERE t2.id = NEW.ticketFk AND ts.alertLevel < al.id AND t1.companyFk = t2.companyFk
AND t1.agencyModeFk = t2.agencyModeFk; AND t1.agencyModeFk = t2.agencyModeFk;
SET NEW.`counter` = intcounter; SET NEW.`counter` = vMaxCounter;
END IF; END IF;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -8,7 +8,7 @@ AS SELECT `rs`.`id` AS `truckFk`,
`t`.`routeFk` AS `routeFk`, `t`.`routeFk` AS `routeFk`,
`es`.`id` AS `scanFk`, `es`.`id` AS `scanFk`,
`e`.`id` AS `expeditionFk`, `e`.`id` AS `expeditionFk`,
`r`.`expeditionTruckFk` AS `expeditionTruckFk`, `r`.`roadmapStopFk` AS `roadmapStopFk`,
`t`.`warehouseFk` AS `warehouseFk`, `t`.`warehouseFk` AS `warehouseFk`,
`e`.`created` AS `lastPacked`, `e`.`created` AS `lastPacked`,
`t`.`id` AS `ticketFk` `t`.`id` AS `ticketFk`
@ -18,7 +18,7 @@ FROM (
( (
( (
`vn`.`roadmapStop` `rs` `vn`.`roadmapStop` `rs`
LEFT JOIN `vn`.`routesMonitor` `r` ON(`rs`.`id` = `r`.`expeditionTruckFk`) LEFT JOIN `vn`.`routesMonitor` `r` ON(`rs`.`id` = `r`.`roadmapStopFk`)
) )
LEFT JOIN `vn`.`ticket` `t` ON(`r`.`routeFk` = `t`.`routeFk`) LEFT JOIN `vn`.`ticket` `t` ON(`r`.`routeFk` = `t`.`routeFk`)
) )

View File

@ -6,7 +6,7 @@ AS SELECT `rs2`.`description` AS `truck`,
`r`.`description` AS `zone`, `r`.`description` AS `zone`,
COUNT(`es`.`id`) AS `eti`, COUNT(`es`.`id`) AS `eti`,
`ep`.`id` AS `palletFk`, `ep`.`id` AS `palletFk`,
`rs`.`id` <=> `rm`.`expeditionTruckFk` AS `isMatch`, `rs`.`id` <=> `rm`.`roadmapStopFk` AS `isMatch`,
`t`.`warehouseFk` AS `warehouseFk`, `t`.`warehouseFk` AS `warehouseFk`,
IF( IF(
`r`.`created` > `util`.`VN_CURDATE`() + INTERVAL 1 DAY, `r`.`created` > `util`.`VN_CURDATE`() + INTERVAL 1 DAY,
@ -33,7 +33,7 @@ FROM (
) )
LEFT JOIN `vn`.`routesMonitor` `rm` ON(`rm`.`routeFk` = `r`.`id`) LEFT JOIN `vn`.`routesMonitor` `rm` ON(`rm`.`routeFk` = `r`.`id`)
) )
LEFT JOIN `vn`.`roadmapStop` `rs2` ON(`rs2`.`id` = `rm`.`expeditionTruckFk`) LEFT JOIN `vn`.`roadmapStop` `rs2` ON(`rs2`.`id` = `rm`.`roadmapStopFk`)
) )
GROUP BY `ep`.`id`, GROUP BY `ep`.`id`,
`t`.`routeFk` `t`.`routeFk`

View File

@ -15,7 +15,7 @@ FROM (
`vn`.`route` `r` `vn`.`route` `r`
LEFT JOIN `vn`.`routesMonitor` `rm` ON(`r`.`id` = `rm`.`routeFk`) LEFT JOIN `vn`.`routesMonitor` `rm` ON(`r`.`id` = `rm`.`routeFk`)
) )
LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rs`.`id` = `rm`.`expeditionTruckFk`) LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rs`.`id` = `rm`.`roadmapStopFk`)
) )
JOIN `vn`.`ticket` `t` ON(`t`.`routeFk` = `r`.`id`) JOIN `vn`.`ticket` `t` ON(`t`.`routeFk` = `r`.`id`)
) )

View File

@ -45,7 +45,7 @@ FROM (
) )
LEFT JOIN `vn`.`routesMonitor` `rm` ON(`rm`.`routeFk` = `t`.`routeFk`) LEFT JOIN `vn`.`routesMonitor` `rm` ON(`rm`.`routeFk` = `t`.`routeFk`)
) )
LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rs`.`id` = `rm`.`expeditionTruckFk`) LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rs`.`id` = `rm`.`roadmapStopFk`)
) )
LEFT JOIN `vn`.`beach` `b` ON(`b`.`code` = `rm`.`beachFk`) LEFT JOIN `vn`.`beach` `b` ON(`b`.`code` = `rm`.`beachFk`)
) )

View File

@ -13,7 +13,7 @@ FROM (
) )
JOIN `vn`.`routesMonitor` `rm` ON(`rm`.`routeFk` = `t`.`routeFk`) JOIN `vn`.`routesMonitor` `rm` ON(`rm`.`routeFk` = `t`.`routeFk`)
) )
JOIN `vn`.`roadmapStop` `rs` ON(`rs`.`id` = `rm`.`expeditionTruckFk`) JOIN `vn`.`roadmapStop` `rs` ON(`rs`.`id` = `rm`.`roadmapStopFk`)
) )
WHERE `e`.`id` IS NULL WHERE `e`.`id` IS NULL
AND `rs`.`eta` > `util`.`VN_CURDATE`() AND `rs`.`eta` > `util`.`VN_CURDATE`()

View File

@ -1,19 +0,0 @@
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn`.`expeditionTruck_Control`
AS SELECT `e`.`truckFk` AS `id`,
`e`.`eta` AS `ETD`,
`e`.`description` AS `description`,
COUNT(
DISTINCT IF(`e`.`expeditionFk` IS NULL, `e`.`ticketFk`, NULL)
) AS `ticketsSinBultos`,
COUNT(DISTINCT `e`.`palletFk`) AS `pallets`,
COUNT(DISTINCT `e`.`routeFk`) AS `routes`,
COUNT(DISTINCT `e`.`scanFk`) AS `scans`,
COUNT(DISTINCT `e`.`expeditionFk`) AS `expeditions`,
sum(`e`.`truckFk` <> `e`.`expeditionTruckFk`) AS `fallos`,
max(`e`.`lastPacked`) AS `lastPacked`
FROM `vn`.`expeditionCommon` `e`
GROUP BY `e`.`truckFk`
ORDER BY sum(`e`.`truckFk` <> `e`.`expeditionTruckFk`) DESC,
`e`.`eta`

View File

@ -1,18 +0,0 @@
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn`.`expeditionTruck_Control_Detail`
AS SELECT `e`.`truckFk` AS `id`,
`e`.`eta` AS `eta`,
`e`.`description` AS `destino`,
`e`.`palletFk` AS `pallet`,
COUNT(DISTINCT `e`.`routeFk`) AS `routes`,
COUNT(DISTINCT `e`.`scanFk`) AS `scans`,
COUNT(DISTINCT `e`.`expeditionTruckFk`) AS `destinos`,
sum(`e`.`truckFk` <> `e`.`expeditionTruckFk`) AS `fallos`,
max(`e`.`lastPacked`) AS `lastPacked`
FROM `vn`.`expeditionCommon` `e`
GROUP BY `e`.`truckFk`,
`e`.`palletFk`
ORDER BY sum(`e`.`truckFk` <> `e`.`expeditionTruckFk`) DESC,
`e`.`eta`,
`e`.`truckFk`

View File

@ -1,22 +0,0 @@
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn`.`expeditionTruck_Control_Detail_Pallet`
AS SELECT `e`.`truckFk` AS `id`,
`e`.`eta` AS `eta`,
`e`.`description` AS `destino`,
`e`.`palletFk` AS `pallet`,
`e`.`routeFk` AS `route`,
COUNT(DISTINCT `e`.`scanFk`) AS `scans`,
`rs`.`description` AS `destinos`,
sum(`e`.`truckFk` <> `e`.`expeditionTruckFk`) AS `fallos`,
`e`.`expeditionTruckFk` AS `expeditionTruckFk`,
max(`e`.`lastPacked`) AS `lastPacked`
FROM (
`vn`.`expeditionCommon` `e`
LEFT JOIN `vn`.`roadmapStop` `rs` ON(`rs`.`id` = `e`.`expeditionTruckFk`)
)
GROUP BY `e`.`truckFk`,
`e`.`palletFk`,
`e`.`routeFk`
ORDER BY sum(`e`.`truckFk` <> `e`.`expeditionTruckFk`) DESC,
`e`.`palletFk`

View File

@ -1,10 +0,0 @@
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn2008`.`Saldos_Prevision`
AS SELECT `fb`.`id` AS `Saldos_Prevision_id`,
`fb`.`description` AS `Descripcion`,
`fb`.`amount` AS `Importe`,
`fb`.`dated` AS `Fecha`,
`fb`.`accountingFk` AS `Id_Banco`,
`fb`.`companyFk` AS `empresa_id`
FROM `vn`.`forecastedBalance` `fb`

View File

@ -21,7 +21,6 @@ AS SELECT `t`.`id` AS `Id_Ticket`,
`t`.`workerFk` AS `Id_Trabajador`, `t`.`workerFk` AS `Id_Trabajador`,
`t`.`observations` AS `Observaciones`, `t`.`observations` AS `Observaciones`,
`t`.`isSigned` AS `Firmado`, `t`.`isSigned` AS `Firmado`,
`t`.`isLabeled` AS `Etiquetasemitidas`,
`t`.`isPrinted` AS `PedidoImpreso`, `t`.`isPrinted` AS `PedidoImpreso`,
`t`.`hour` AS `Hora`, `t`.`hour` AS `Hora`,
`t`.`isBlocked` AS `blocked`, `t`.`isBlocked` AS `blocked`,

View File

@ -0,0 +1,8 @@
CREATE TABLE `vn`.`roadmapAddress` (
addressFk int(11) NULL,
isActive TINYINT DEFAULT 1 NULL,
PRIMARY KEY (addressFk)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Direcciones de los troncales';
ALTER TABLE vn.roadmapAddress
ADD CONSTRAINT roadmapAddress_address_FK FOREIGN KEY (addressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,7 @@
ALTER TABLE vn.roadmapStop DROP FOREIGN KEY expeditionTruck_FK_1;
ALTER TABLE vn.roadmapStop DROP COLUMN warehouseFk;
ALTER TABLE vn.roadmapStop ADD addressFk int(11) NULL;
ALTER TABLE vn.roadmapStop CHANGE addressFk addressFk int(11) DEFAULT NULL NULL AFTER roadmapFk;
ALTER TABLE vn.roadmapStop
ADD CONSTRAINT roadmapStop_roadmapAddress_FK FOREIGN KEY (addressFk) REFERENCES vn.roadmapAddress(addressFk) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,11 @@
DELETE FROM salix.ACL
WHERE model in ('expeditionTruck', 'Roadmap', 'roadmapStop', 'roadmapAddress');
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
VALUES
('RoadmapAddress', '*', 'WRITE', 'ALLOW', 'ROLE', 'palletizerBoss'),
('RoadmapAddress', '*', 'READ', 'ALLOW', 'ROLE', 'production'),
('Roadmap', '*', 'WRITE', 'ALLOW', 'ROLE', 'palletizerBoss'),
('Roadmap', '*', 'READ', 'ALLOW', 'ROLE', 'production'),
('RoadmapStop', '*', 'WRITE', 'ALLOW', 'ROLE', 'palletizerBoss'),
('RoadmapStop', '*', 'READ', 'ALLOW', 'ROLE', 'production');

View File

@ -0,0 +1,5 @@
-- Place your SQL code here
USE vn;
ALTER TABLE vn.productionConfig ADD itemOlderReviewHours int(11) DEFAULT 0 NOT NULL COMMENT 'Horas que se tienen en cuenta para comprobar si un ítem es más viejo.';

View File

@ -0,0 +1,3 @@
ALTER TABLE vn.routesMonitor CHANGE expeditionTruckFk roadmapStopFk int(11) DEFAULT NULL NULL;
ALTER TABLE vn.routesMonitor ADD COLUMN expeditionTruckFk int(11) AS (roadmapStopFk) VIRTUAL;

View File

@ -0,0 +1 @@
ALTER TABLE vn.country DROP COLUMN country;

View File

@ -0,0 +1,9 @@
CREATE TABLE `vn`.`clientRate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`clientFk` int(11) NOT NULL,
`dated` date NOT NULL DEFAULT current_timestamp(),
`value` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `clientRate_unique` (`clientFk`,`dated`),
CONSTRAINT `clientRate_client_FK` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;

View File

@ -0,0 +1,4 @@
ALTER TABLE vn.ticket MODIFY COLUMN IF EXISTS isLabeled__ tinyint(1) DEFAULT 0 NOT NULL COMMENT 'refs #7496 deprecated 2024-06-20';
ALTER TABLE IF EXISTS vn.forecastedBalance RENAME vn.forecastedBalance__ ;
ALTER TABLE IF EXISTS vn.forecastedBalance__ COMMENT='@deprecated 2024-05-21';

View File

@ -0,0 +1,5 @@
-- Place your SQL code here
USE vn;
ALTER TABLE vn.expeditionState ADD isScanned tinyint(1) DEFAULT false NOT NULL;

View File

@ -0,0 +1,4 @@
UPDATE salix.ACL
SET property = 'cmrs'
WHERE property = 'getExternalCmrs'
AND model = 'Route';

View File

@ -0,0 +1,3 @@
ALTER TABLE vn.client
CHANGE hasIncoterms hasIncoterms__ tinyint(1) DEFAULT 0 NOT NULL
COMMENT '@deprecated 2024-06-12 refs #7545 Received incoterms authorization from client';

View File

@ -0,0 +1,17 @@
CREATE TABLE IF NOT EXISTS vn.travelKgPercentage (
value INT(3) PRIMARY KEY,
className VARCHAR(50)
);
INSERT INTO vn.travelKgPercentage (value, className)
VALUES
(80, 'primary'),
(100, 'alert');
INSERT INTO salix.ACL
SET model = 'TravelKgPercentage',
property = '*',
accessType = 'READ',
permission = 'ALLOW',
principalType = 'ROLE',
principalId = 'employee';

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.ticketPackaging DROP FOREIGN KEY ticketPackaging_fk3;
ALTER TABLE vn.ticketPackaging DROP COLUMN workerFk;

View File

@ -0,0 +1,9 @@
-- Place your SQL code here
USE vn;
ALTER TABLE vn.productionConfig ADD sectorFromCode varchar(15) NULL COMMENT 'Sector origen que se revisa ítems más nuevos al parkinear';
ALTER TABLE vn.productionConfig ADD sectorToCode varchar(15) NULL COMMENT 'Sector destino que se revisa ítems más nuevos al parkinear';
ALTER TABLE vn.productionConfig ADD CONSTRAINT productionConfig_sector_FK FOREIGN KEY (sectorFromCode) REFERENCES vn.sector(code) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE vn.productionConfig ADD CONSTRAINT productionConfig_sector_FK_1 FOREIGN KEY (sectorToCode) REFERENCES vn.sector(code) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,4 @@
ALTER TABLE vn.clientUnpaid
ADD editorFk INT UNSIGNED NULL,
ADD CONSTRAINT ClientUnpaid_editorFk FOREIGN KEY (editorFk)
REFERENCES account.`user`(id);

View File

@ -33,106 +33,4 @@ describe('Travel descriptor path', () => {
expect(state).toBe('travel.card.summary'); expect(state).toBe('travel.card.summary');
}); });
it('should be redirected to the create entry view', async() => {
await page.waitToClick(selectors.travelDescriptor.dotMenu);
await page.waitToClick(selectors.travelDescriptor.dotMenuAddEntry);
await page.waitForState('entry.create');
const state = await page.getState();
expect(state).toBe('entry.create');
});
it('should check some data was imported from the travel', async() => {
const travel = await page.waitToGetProperty(selectors.entryCreate.travel, 'value');
const campany = await page.waitToGetProperty(selectors.entryCreate.company, 'value');
expect(travel).toContain('Warehouse');
expect(campany).toContain('VNL');
});
it('should navigate back to the travel index', async() => {
await page.waitToClick('.cancel');
await page.waitToClick(selectors.globalItems.homeButton);
await page.selectModule('travel');
await page.waitForState('travel.index');
const state = await page.getState();
expect(state).toBe('travel.index');
});
it('should click on the add entry button of the third result to be redirected to create entry', async() => {
await page.keyboard.press('Enter');
await page.waitToClick(selectors.travelIndex.firstTravelAddEntryButton);
await page.waitForState('entry.create');
const state = await page.getState();
expect(state).toBe('entry.create');
});
it('should check again some data was imported from the travel', async() => {
const travel = await page.waitToGetProperty(selectors.entryCreate.travel, 'value');
const campany = await page.waitToGetProperty(selectors.entryCreate.company, 'value');
expect(travel).toContain('Warehouse');
expect(campany).toContain('VNL');
});
it('should navigate to the travel summary of a given travel', async() => {
await page.waitToClick('.cancel');
await page.waitToClick(selectors.globalItems.homeButton);
await page.selectModule('travel');
await page.write(selectors.travelIndex.generalSearchFilter, '3');
await page.keyboard.press('Enter');
await page.waitForState('travel.card.summary');
const state = await page.getState();
expect(state).toBe('travel.card.summary');
});
it('should be redirected to the create travel when using the clone option of the dot menu', async() => {
await page.waitToClick(selectors.travelDescriptor.dotMenu);
await page.waitToClick(selectors.travelDescriptor.dotMenuClone);
await page.respondToDialog('accept');
await page.waitForState('travel.create');
const state = await page.getState();
expect(state).toBe('travel.create');
});
it('should edit the data to clone and then get redirected to the cloned travel basic data', async() => {
await page.clearInput(selectors.travelCreate.reference);
await page.write(selectors.travelCreate.reference, 'reference');
await page.autocompleteSearch(selectors.travelCreate.agency, 'entanglement');
await page.pickDate(selectors.travelCreate.shipped);
await page.pickDate(selectors.travelCreate.landed);
await page.autocompleteSearch(selectors.travelCreate.warehouseOut, 'warehouse one');
await page.autocompleteSearch(selectors.travelCreate.warehouseIn, 'warehouse two');
await page.waitToClick(selectors.travelCreate.saveButton);
await page.waitForState('travel.card.basicData');
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should update the landed date to a future date to enable cloneWithEntries', async() => {
const nextMonth = Date.vnNew();
nextMonth.setMonth(nextMonth.getMonth() + 1);
await page.pickDate(selectors.travelBasicData.deliveryDate, nextMonth);
await page.waitToClick(selectors.travelBasicData.save);
await page.waitForState('travel.card.basicData');
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should navigate to the summary and then clone the travel and its entries using the descriptor menu to get redirected to the cloned travel basic data', async() => {
await page.waitToClick('vn-icon[icon="launch"]');
await page.waitForState('travel.card.summary');
await page.waitForTimeout(1000);
await page.waitToClick(selectors.travelDescriptor.dotMenu);
await page.waitToClick(selectors.travelDescriptor.dotMenuCloneWithEntries);
await page.waitToClick(selectors.travelDescriptor.acceptClonation);
await page.waitForState('travel.card.basicData');
});
}); });

View File

@ -1,47 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry summary path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
await page.accessToSearchResult('4');
});
afterAll(async() => {
await browser.close();
});
it('should reach the second entry summary section', async() => {
await page.waitForState('entry.card.summary');
});
it(`should display details from the entry on the header`, async() => {
await page.waitForTextInElement(selectors.entrySummary.header, 'The farmer');
const result = await page.waitToGetProperty(selectors.entrySummary.header, 'innerText');
expect(result).toContain('The farmer');
});
it('should display some entry details like the reference', async() => {
const result = await page.waitToGetProperty(selectors.entrySummary.reference, 'innerText');
expect(result).toContain('Movement 4');
});
it('should display other entry details like the confirmed', async() => {
const result = await page.checkboxState(selectors.entrySummary.confirmed, 'innerText');
expect(result).toContain('unchecked');
});
it('should display all buys for the entry', async() => {
const result = await page.countElement(selectors.entrySummary.anyBuyLine);
expect(result).toEqual(4);
});
});

View File

@ -1,49 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry descriptor path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
await page.accessToSearchResult('2');
});
afterAll(async() => {
await browser.close();
});
it('should reach the second entry summary section', async() => {
await page.waitForState('entry.card.summary');
});
it('should show some entry information', async() => {
const result = await page.waitToGetProperty(selectors.entryDescriptor.agency, 'innerText');
expect(result).toContain('inhouse pickup');
});
it('should click the travels button to be redirected to the travels index filtered by the current agency', async() => {
await page.waitToClick(selectors.entryDescriptor.travelsQuicklink);
await page.expectURL('/travel/index');
await page.expectURL('agencyModeFk');
});
it('should go back to the entry summary', async() => {
await page.waitToClick(selectors.globalItems.homeButton);
await page.selectModule('entry');
await page.accessToSearchResult('2');
await page.waitForState('entry.card.summary');
});
it('should click the entries button to be redirected to the entries index filtered by the current supplier', async() => {
await page.waitToClick(selectors.entryDescriptor.entriesQuicklink);
await page.expectURL('/entry/index');
await page.expectURL('supplierFk');
await page.expectURL('to');
await page.expectURL('from');
});
});

View File

@ -1,116 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry lastest buys path', () => {
let browser;
let page;
const httpRequests = [];
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
page.on('request', req => {
if (req.url().includes(`Buys/latestBuysFilter`))
httpRequests.push(req.url());
});
await page.loginAndModule('buyer', 'entry');
});
afterAll(async() => {
await browser.close();
});
it('should access the latest buys seccion and search not seeing the edit buys button yet', async() => {
await page.waitToClick(selectors.entryLatestBuys.latestBuysSectionButton);
await page.waitForSelector(selectors.entryLatestBuys.editBuysButton, {visible: false});
});
it('should filter by name', async() => {
await page.write(selectors.entryLatestBuys.generalSearchInput, 'Melee');
await page.keyboard.press('Enter');
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('search=Melee')))).toBeDefined();
});
it('should filter by reign and type', async() => {
await page.click(selectors.entryLatestBuys.firstReignIcon);
await page.autocompleteSearch(selectors.entryLatestBuys.typeInput, 'Alstroemeria');
await page.click(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('categoryFk')))).toBeDefined();
expect(httpRequests.find(req => req.includes(('typeFk')))).toBeDefined();
});
it('should filter by sales person', async() => {
await page.autocompleteSearch(selectors.entryLatestBuys.salesPersonInput, 'buyerNick');
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('salesPersonFk')))).toBeDefined();
});
it('should filter by supplier', async() => {
await page.autocompleteSearch(selectors.entryLatestBuys.supplierInput, 'Farmer King');
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('supplierFk')))).toBeDefined();
});
it('should filter by active', async() => {
await page.waitToClick(selectors.entryLatestBuys.activeCheck);
await page.waitToClick(selectors.entryLatestBuys.activeCheck);
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('active=true')))).toBeDefined();
expect(httpRequests.find(req => req.includes(('active=false')))).toBeDefined();
});
it('should filter by visible', async() => {
await page.waitToClick(selectors.entryLatestBuys.visibleCheck);
await page.waitToClick(selectors.entryLatestBuys.visibleCheck);
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('visible=true')))).toBeDefined();
expect(httpRequests.find(req => req.includes(('visible=false')))).toBeDefined();
});
it('should filter by floramondo', async() => {
await page.waitToClick(selectors.entryLatestBuys.floramondoCheck);
await page.waitToClick(selectors.entryLatestBuys.floramondoCheck);
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('floramondo=true')))).toBeDefined();
expect(httpRequests.find(req => req.includes(('floramondo=false')))).toBeDefined();
});
it('should filter by tag Color', async() => {
await page.waitToClick(selectors.entryLatestBuys.addTagButton);
await page.autocompleteSearch(selectors.entryLatestBuys.itemTagInput, 'Color');
await page.autocompleteSearch(selectors.entryLatestBuys.itemTagValueInput, 'Brown');
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('tags')))).toBeDefined();
});
it('should select all lines but one and then check the edit buys button appears', async() => {
await page.waitToClick(selectors.entryLatestBuys.allBuysCheckBox);
await page.waitToClick(selectors.entryLatestBuys.secondBuyCheckBox);
await page.waitForSelector(selectors.entryLatestBuys.editBuysButton, {visible: true});
});
it('should open the edit dialog', async() => {
await page.waitToClick(selectors.entryLatestBuys.editBuysButton);
await page.waitForSelector(selectors.entryLatestBuys.fieldAutocomplete, {visible: true});
});
it('should search for the "Description" and type a new one for the items in each selected buy', async() => {
await page.autocompleteSearch(selectors.entryLatestBuys.fieldAutocomplete, 'Description');
await page.write(selectors.entryLatestBuys.newValueInput, 'Crafted item');
await page.waitToClick(selectors.entryLatestBuys.acceptEditBuysDialog);
});
it('should navigate to the entry.buy section by clicking one of the buys', async() => {
await page.waitToClick(selectors.entryLatestBuys.firstBuy);
await page.waitForState('entry.card.buy.index');
});
});

View File

@ -1,34 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry create path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
});
afterAll(async() => {
await browser.close();
});
it('should click the create entry button to open the form', async() => {
await page.waitToClick(selectors.entryIndex.createEntryButton);
await page.waitForState('entry.create');
});
it('should fill the form to create a valid entry then redirect to basic Data', async() => {
await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, 'The farmer');
await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse');
await page.autocompleteSearch(selectors.entryIndex.newEntryCompany, 'ORN');
await page.waitToClick(selectors.entryIndex.saveNewEntry);
await page.waitForNavigation({
waitUntil: 'load',
});
await page.waitForState('entry.card.basicData');
});
});

View File

@ -1,81 +0,0 @@
import getBrowser from '../../helpers/puppeteer';
const $ = {
reference: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.reference"]',
invoiceNumber: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.invoiceNumber"]',
notes: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.notes"]',
observations: 'vn-entry-basic-data vn-textarea[ng-model="$ctrl.entry.observation"]',
supplier: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]',
currency: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.currencyFk"]',
commission: 'vn-entry-basic-data vn-input-number[ng-model="$ctrl.entry.commission"]',
company: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.companyFk"]',
ordered: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isOrdered"]',
confirmed: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isConfirmed"]',
inventory: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isExcludedFromAvailable"]',
raid: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isRaid"]',
booked: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isBooked"]',
save: 'vn-entry-basic-data button[type=submit]',
};
describe('Entry basic data path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
await page.accessToSearchResult('2');
await page.accessToSection('entry.card.basicData');
});
afterAll(async() => {
await browser.close();
});
it('should edit the basic data and confirm the reference was edited', async() => {
await page.write($.reference, 'new movement 8');
await page.write($.invoiceNumber, 'new movement 8');
await page.write($.observations, ' edited');
await page.autocompleteSearch($.supplier, 'Plants nick');
await page.autocompleteSearch($.currency, 'eur');
await page.clearInput($.commission);
await page.write($.commission, '100');
await page.autocompleteSearch($.company, 'CCs');
await page.waitToClick($.ordered);
await page.waitToClick($.confirmed);
await page.waitToClick($.inventory);
await page.waitToClick($.raid);
await page.waitToClick($.booked);
await page.waitToClick($.save);
const message = await page.waitForSnackbar();
await page.reloadSection('entry.card.basicData');
const reference = await page.waitToGetProperty($.reference, 'value');
const supplier = await page.waitToGetProperty($.supplier, 'value');
const invoiceNumber = await page.waitToGetProperty($.invoiceNumber, 'value');
const observations = await page.waitToGetProperty($.observations, 'value');
const currency = await page.waitToGetProperty($.currency, 'value');
const commission = await page.waitToGetProperty($.commission, 'value');
const company = await page.waitToGetProperty($.company, 'value');
const ordered = await page.checkboxState($.ordered);
const confirmed = await page.checkboxState($.confirmed);
const inventory = await page.checkboxState($.inventory);
const raid = await page.checkboxState($.raid);
const booked = await page.checkboxState($.booked);
expect(message.text).toContain('Data saved!');
expect(reference).toEqual('new movement 8');
expect(supplier).toEqual('Plants nick');
expect(invoiceNumber).toEqual('new movement 8');
expect(observations).toEqual('observation two edited');
expect(currency).toEqual('EUR');
expect(commission).toEqual('100');
expect(company).toEqual('CCs');
expect(ordered).toBe('checked');
expect(confirmed).toBe('checked');
expect(inventory).toBe('checked');
expect(raid).toBe('checked');
expect(booked).toBe('unchecked');
});
});

View File

@ -1,65 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry observations path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
await page.accessToSearchResult('2');
await page.accessToSection('entry.card.observation');
});
afterAll(async() => {
await browser.close();
});
it(`should add two new observations of the same type then fail to save as they can't be repeated`, async() => {
await page.waitToClick(selectors.entryObservations.addNewObservation);
await page.waitToClick(selectors.entryObservations.addNewObservation);
await page.autocompleteSearch(selectors.entryObservations.firstObservationType, 'SalesPerson');
await page.autocompleteSearch(selectors.entryObservations.secondObservationType, 'SalesPerson');
await page.write(selectors.entryObservations.firstObservationDescription, 'first observation');
await page.write(selectors.entryObservations.secondObservationDescription, 'second observation');
await page.waitToClick(selectors.entryObservations.saveObservationsButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain(`The observation type can't be repeated`);
});
it('should set the 2nd observation of a different one and successfully save both', async() => {
await page.autocompleteSearch(selectors.entryObservations.secondObservationType, 'Delivery');
await page.waitToClick(selectors.entryObservations.saveObservationsButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should reload the section and make sure the first observation type was saved correctly', async() => {
await page.reloadSection('entry.card.observation');
const result = await page.waitToGetProperty(selectors.entryObservations.firstObservationType, 'value');
expect(result).toEqual('SalesPerson');
});
it('should make sure the first observation description was saved correctly', async() => {
const result = await page.waitToGetProperty(selectors.entryObservations.firstObservationDescription, 'value');
expect(result).toEqual('first observation');
});
it('should make sure the second observation type was saved correctly', async() => {
const result = await page.waitToGetProperty(selectors.entryObservations.secondObservationType, 'value');
expect(result).toEqual('Delivery');
});
it('should make sure the second observation description was saved correctly', async() => {
const result = await page.waitToGetProperty(selectors.entryObservations.secondObservationDescription, 'value');
expect(result).toEqual('second observation');
});
});

View File

@ -1,69 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry import, create and edit buys path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
await page.accessToSearchResult('3');
});
afterAll(async() => {
await browser.close();
});
it('should count the summary buys and find there only one at this point', async() => {
const buysCount = await page.countElement(selectors.entrySummary.anyBuyLine);
expect(buysCount).toEqual(2);
});
it('should navigate to the buy section and then click the import button opening the import form', async() => {
await page.accessToSection('entry.card.buy.index');
await page.waitToClick(selectors.entryBuys.importButton);
await page.waitForState('entry.card.buy.import');
});
it('should fill the form, import the a JSON file and select items for each import and confirm import', async() => {
let currentDir = process.cwd();
let filePath = `${currentDir}/e2e/assets/07_import_buys.json`;
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.waitToClick(selectors.entryBuys.file)
]);
await fileChooser.accept([filePath]);
await page.waitForTextInField(selectors.entryBuys.ref, '200573095, 200573106, 200573117, 200573506');
await page.waitForTextInField(selectors.entryBuys.observation, '729-6340 2846');
await page.autocompleteSearch(selectors.entryBuys.firstImportedItem, 'Ranged weapon longbow 200cm');
await page.autocompleteSearch(selectors.entryBuys.secondImportedItem, 'Ranged weapon longbow 200cm');
await page.autocompleteSearch(selectors.entryBuys.thirdImportedItem, 'Ranged weapon sniper rifle 113cm');
await page.autocompleteSearch(selectors.entryBuys.fourthImportedItem, 'Melee weapon heavy shield 100cm');
await page.waitToClick(selectors.entryBuys.importBuysButton);
const message = await page.waitForSnackbar();
const state = await page.getState();
expect(message.text).toContain('Data saved!');
expect(state).toBe('entry.card.buy.index');
});
it('should count the buys to find 4 buys have been added', async() => {
await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 6);
});
it('should delete the four buys that were just added', async() => {
await page.waitToClick(selectors.entryBuys.allBuyCheckbox);
await page.waitToClick(selectors.entryBuys.firstBuyCheckbox);
await page.waitToClick(selectors.entryBuys.deleteBuysButton);
await page.waitToClick(selectors.globalItems.acceptButton);
await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 1);
});
});

View File

@ -65,11 +65,6 @@ describe('Supplier summary & descriptor path', () => {
await page.waitForState('supplier.card.summary'); await page.waitForState('supplier.card.summary');
}); });
it(`should navigate to the supplier's entries`, async() => {
await page.waitToClick(selectors.supplierDescriptor.entriesButton);
await page.waitForState('entry.index');
});
it(`should navigate back to suppliers but a different one this time`, async() => { it(`should navigate back to suppliers but a different one this time`, async() => {
await page.waitToClick(selectors.globalItems.homeButton); await page.waitToClick(selectors.globalItems.homeButton);
await page.waitForState('home'); await page.waitForState('home');

View File

@ -1,27 +1,27 @@
export default function moduleImport(moduleName) { export default function moduleImport(moduleName) {
// TODO: Webpack watches module backend files when using dynamic import // TODO: Webpack watches module backend files when using dynamic import
//return import( // return import(
// /* webpackInclude: /modules\/[a-z0-9-]+\/front\/index.js$/ */ // /* webpackInclude: /modules\/[a-z0-9-]+\/front\/index.js$/ */
// '../modules/'+ moduleName +'/front/index.js' // '../modules/'+ moduleName +'/front/index.js'
//); // );
switch(moduleName) { switch (moduleName) {
case 'client' : return import('client/front'); case 'client': return import('client/front');
case 'item' : return import('item/front'); case 'item': return import('item/front');
case 'ticket' : return import('ticket/front'); case 'ticket': return import('ticket/front');
case 'order' : return import('order/front'); case 'order': return import('order/front');
case 'claim' : return import('claim/front'); case 'claim': return import('claim/front');
case 'zone' : return import('zone/front'); case 'zone': return import('zone/front');
case 'travel' : return import('travel/front'); case 'travel': return import('travel/front');
case 'worker' : return import('worker/front'); case 'worker': return import('worker/front');
case 'invoiceOut' : return import('invoiceOut/front'); case 'invoiceOut': return import('invoiceOut/front');
case 'invoiceIn' : return import('invoiceIn/front'); case 'invoiceIn': return import('invoiceIn/front');
case 'route' : return import('route/front'); case 'route': return import('route/front');
case 'entry' : return import('entry/front'); case 'account': return import('account/front');
case 'account' : return import('account/front'); case 'supplier': return import('supplier/front');
case 'supplier' : return import('supplier/front'); case 'shelving': return import('shelving/front');
case 'shelving' : return import('shelving/front'); case 'monitor': return import('monitor/front');
case 'monitor' : return import('monitor/front'); case 'entry': return import('entry/front');
} }
} }

View File

@ -231,6 +231,7 @@
"You can only have one PDA": "You can only have one PDA", "You can only have one PDA": "You can only have one PDA",
"Incoterms and Customs agent are required for a non UEE member": "Incoterms and Customs agent are required for a non UEE member", "Incoterms and Customs agent are required for a non UEE member": "Incoterms and Customs agent are required for a non UEE member",
"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 send mail": "Cannot send mail"
} }

View File

@ -364,5 +364,7 @@
"This PDA is already assigned to another user": "Este PDA ya está asignado a otro usuario", "This PDA is already assigned to another user": "Este PDA ya está asignado a otro usuario",
"You can only have one PDA": "Solo puedes tener un PDA", "You can only have one PDA": "Solo puedes tener un PDA",
"It has been invoiced but the PDF could not be generated": "Se ha facturado pero no se ha podido generar el PDF", "It has been invoiced but the PDF could not be generated": "Se ha facturado pero no se ha podido generar el PDF",
"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",
"Cannot send mail": "Não é possível enviar o email"
} }

View File

@ -359,5 +359,6 @@
"Select ticket or client": "Choisissez un ticket ou un client", "Select ticket or client": "Choisissez un ticket ou un client",
"It was not able to create the invoice": "Il n'a pas été possible de créer la facture", "It was not able to create the invoice": "Il n'a pas été possible de créer la facture",
"It has been invoiced but the PDF could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré", "It has been invoiced but the PDF could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré",
"It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré" "It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré",
"Cannot send mail": "Impossible d'envoyer le mail"
} }

View File

@ -1,6 +1,9 @@
{ {
"name": "RoleInherit", "name": "RoleInherit",
"base": "VnModel", "base": "VnModel",
"mixins": {
"Loggable": true
},
"options": { "options": {
"mysql": { "mysql": {
"table": "account.roleInherit" "table": "account.roleInherit"

View File

@ -0,0 +1,5 @@
name: unpaid
columns:
clientFk: client
dated: date
amount: amount

View File

@ -0,0 +1,5 @@
name: impagado
columns:
clientFk: cliente
dated: fecha
amount: cantidad

View File

@ -96,10 +96,6 @@ module.exports = Self => {
arg: 'despiteOfClient', arg: 'despiteOfClient',
type: 'any' type: 'any'
}, },
{
arg: 'hasIncoterms',
type: 'boolean'
},
{ {
arg: 'hasElectronicInvoice', arg: 'hasElectronicInvoice',
type: 'boolean' type: 'boolean'

View File

@ -1,6 +1,9 @@
{ {
"name": "ClientUnpaid", "name": "ClientUnpaid",
"base": "VnModel", "base": "VnModel",
"mixins": {
"Loggable": true
},
"options": { "options": {
"mysql": { "mysql": {
"table": "clientUnpaid" "table": "clientUnpaid"

View File

@ -97,9 +97,6 @@
"hasCoreVnh": { "hasCoreVnh": {
"type": "boolean" "type": "boolean"
}, },
"hasIncoterms": {
"type": "boolean"
},
"isTaxDataChecked":{ "isTaxDataChecked":{
"type": "boolean" "type": "boolean"
}, },

View File

@ -184,11 +184,6 @@
</vn-check> </vn-check>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-check
label="Incoterms authorization"
ng-model="$ctrl.client.hasIncoterms"
vn-acl="administrative">
</vn-check>
<vn-check <vn-check
label="Electronic invoice" label="Electronic invoice"
ng-model="$ctrl.client.hasElectronicInvoice" ng-model="$ctrl.client.hasElectronicInvoice"

View File

@ -48,7 +48,8 @@ module.exports = Self => {
'weight', 'weight',
'buyingValue', 'buyingValue',
'price2', 'price2',
'price3' 'price3',
'printedStickers'
], ],
include: { include: {
relation: 'item', relation: 'item',

View File

@ -1,234 +0,0 @@
<mg-ajax path="Entries/{{patch.params.id}}" options="vnPatch"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.entry"
form="form"
save="patch">
</vn-watcher>
<vn-crud-model
auto-load="true"
url="Warehouses"
data="warehouses">
</vn-crud-model>
<form name="form" ng-submit="watcher.submit()" class="vn-w-md">
<vn-card class="vn-pa-lg">
<vn-horizontal>
<vn-autocomplete
vn-one
ng-model="$ctrl.entry.supplierFk"
url="Suppliers"
show-field="nickname"
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
value-field="id"
order="nickname"
label="Supplier"
required="true">
<tpl-item>
<div>#{{::nickname}}</div>
<div class="text-secondary text-caption">#{{::id}}</div>
</tpl-item>
</vn-autocomplete>
<vn-autocomplete
vn-one
ng-model="$ctrl.entry.travelFk"
url="Travels/filter"
search-function="$ctrl.searchFunction($search)"
value-field="id"
show-field="warehouseInName"
order="id"
label="Travel"
required="true">
<tpl-item>
<div>
{{::agencyModeName}} - {{::warehouseInName}} ({{::shipped | date: 'dd/MM/yyyy'}}) &#x2192;
{{::warehouseOutName}} ({{::landed | date: 'dd/MM/yyyy'}})
</div>
<div class="text-secondary text-caption">#{{::id}}</div>
</tpl-item>
<append>
<vn-icon-button
icon="filter_alt"
vn-click-stop="$ctrl.showFilterDialog($ctrl.entry.travelFk)"
vn-tooltip="Filter...">
</vn-icon-button>
</append>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-textfield
vn-one
label="Reference"
ng-model="$ctrl.entry.reference"
rule
vn-focus>
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield
vn-one
label="Invoice number"
ng-model="$ctrl.entry.invoiceNumber"
rule
vn-focus>
</vn-textfield>
<vn-autocomplete
url="Companies"
label="Company"
show-field="code"
value-field="id"
ng-model="$ctrl.entry.companyFk">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
label="Currency"
ng-model="$ctrl.entry.currencyFk"
url="Currencies"
show-field="code"
value-field="id">
</vn-autocomplete>
<vn-input-number
vn-one
step="0.1"
label="Commission"
ng-model="$ctrl.entry.commission"
rule>
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-textarea
vn-one
label="Observation"
ng-model="$ctrl.entry.observation"
rule>
</vn-textarea>
</vn-horizontal>
<vn-horizontal>
<vn-check
label="Ordered"
ng-model="$ctrl.entry.isOrdered">
</vn-check>
<vn-check
label="Confirmed"
ng-model="$ctrl.entry.isConfirmed">
</vn-check>
<vn-check
label="Inventory"
ng-model="$ctrl.entry.isExcludedFromAvailable">
</vn-check>
<vn-check
label="Raid"
ng-model="$ctrl.entry.isRaid">
</vn-check>
<vn-check
label="Booked"
ng-model="$ctrl.entry.isBooked"
vn-acl="administrative"
>
</vn-check>
</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>
<!-- Filter travel dialog -->
<vn-dialog
vn-id="filterDialog"
message="Filter travel">
<tpl-body class="travelFilter">
<vn-horizontal>
<vn-autocomplete
label="Agency"
ng-model="$ctrl.travelFilterParams.agencyModeFk"
url="AgencyModes"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete
label="Warehouse Out"
ng-model="$ctrl.travelFilterParams.warehouseOutFk"
data="warehouses"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete
label="Warehouse In"
ng-model="$ctrl.travelFilterParams.warehouseInFk"
data="warehouses"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-date-picker
label="Shipped"
ng-model="$ctrl.travelFilterParams.shipped">
</vn-date-picker>
<vn-date-picker
label="Landed"
ng-model="$ctrl.travelFilterParams.landed">
</vn-date-picker>
</vn-horizontal>
<vn-horizontal class="vn-mb-md">
<vn-button vn-none
label="Search"
ng-click="$ctrl.filter()">
</vn-button>
</vn-horizontal>
<vn-crud-model
vn-id="travelsModel"
url="Travels"
filter="$ctrl.travelFilter"
data="travels"
limit="10">
</vn-crud-model>
<vn-data-viewer
model="travelsModel"
class="vn-w-lg">
<vn-table class="scrollable">
<vn-thead>
<vn-tr>
<vn-th shrink>ID</vn-th>
<vn-th expand>Agency</vn-th>
<vn-th expand>Warehouse Out</vn-th>
<vn-th expand>Warehouse In</vn-th>
<vn-th expand>Shipped</vn-th>
<vn-th expand>Landed</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<a ng-repeat="travel in travels"
class="clickable vn-tr search-result"
ng-click="$ctrl.selectTravel(travel.id)">
<vn-td shrink>
<span
vn-click-stop="travelDescriptor.show($event, travel.id)"
class="link">
{{::travel.id}}
</span>
</vn-td>
<vn-td expand>{{::travel.agency.name}}</vn-td>
<vn-td expand>{{::travel.warehouseOut.name}}</vn-td>
<vn-td expand>{{::travel.warehouseIn.name}}</vn-td>
<vn-td expand>{{::travel.shipped | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td expand>{{::travel.landed | date: 'dd/MM/yyyy'}}</vn-td>
</a>
</vn-tbody>
</vn-table>
</vn-data-viewer>
<vn-travel-descriptor-popover
vn-id="travel-descriptor"
warehouse-fk="$ctrl.vnConfig.warehouseFk">
</vn-travel-descriptor-popover>
</tpl-body>
</vn-dialog>

View File

@ -1,68 +0,0 @@
import ngModule from '../module';
import Section from 'salix/components/section';
import './style.scss';
class Controller extends Section {
showFilterDialog(travel) {
this.activeTravel = travel;
this.travelFilterParams = {};
this.travelFilter = {
include: [
{
relation: 'agency',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseIn',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseOut',
scope: {
fields: ['name']
}
}
]
};
this.$.filterDialog.show();
}
selectTravel(id) {
this.entry.travelFk = id;
this.$.filterDialog.hide();
}
filter() {
const filter = this.travelFilter;
const params = this.travelFilterParams;
const where = {};
for (let key in params) {
const value = params[key];
if (!value) continue;
switch (key) {
case 'agencyModeFk':
case 'warehouseInFk':
case 'warehouseOutFk':
case 'shipped':
case 'landed':
where[key] = value;
}
}
filter.where = where;
this.$.travelsModel.applyFilter(filter);
}
}
ngModule.vnComponent('vnEntryBasicData', {
template: require('./index.html'),
bindings: {
entry: '<'
},
controller: Controller
});

View File

@ -1,3 +0,0 @@
.travelFilter{
width: 950px;
}

View File

@ -1,205 +0,0 @@
<mg-ajax path="dms/upload" options="vnPost"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.dms">
</vn-watcher>
<form
name="form"
ng-submit="$ctrl.onSubmit()"
class="vn-ma-md">
<div class="vn-w-lg">
<vn-card class="vn-pa-lg">
<vn-horizontal>
<vn-input-file
vn-one
label="File"
ng-model="$ctrl.import.file"
on-change="$ctrl.onFileChange($event)"
accept="application/json"
required="true">
<append>
<vn-icon vn-none
color-marginal
title="{{'JSON files only' | translate}}"
icon="info">
</vn-icon>
</append>
</vn-input-file>
</vn-horizontal>
<vn-horizontal ng-show="$ctrl.import.ref">
<vn-textfield vn-focus
vn-one
label="Reference"
ng-model="$ctrl.import.ref">
</vn-textfield>
</vn-horizontal>
<vn-horizontal ng-show="$ctrl.import.observation">
<vn-textarea
vn-one
label="Observation"
ng-model="$ctrl.import.observation">
</vn-textarea>
</vn-horizontal>
<vn-horizontal ng-show="$ctrl.import.buys.length > 0">
<table class="vn-table">
<thead>
<tr>
<th translate>Item</th>
<th translate expand>Description</th>
<th translate center>Size</th>
<th translate center>Packing</th>
<th translate center>Grouping</th>
<th translate center>Buying value</th>
<th translate center>Box</th>
</tr>
</thead>
<tbody ng-repeat="buy in $ctrl.import.buys">
<tr>
<td title="{{::buy.itemFk}}">
<vn-autocomplete
class="dense"
vn-focus
url="Entries/{{$ctrl.$params.id}}/lastItemBuys"
ng-model="buy.itemFk"
show-field="name"
value-field="id"
search-function="$ctrl.itemSearchFunc($search)"
order="id DESC"
tabindex="1">
<tpl-item>
{{::id}} - {{::name}}
</tpl-item>
<append>
<vn-icon-button
icon="filter_alt"
vn-click-stop="$ctrl.showFilterDialog(buy)"
vn-tooltip="Filter...">
</vn-icon-button>
</append>
</vn-autocomplete>
</td>
<td title="{{::buy.description}}" expand>{{::buy.description | dashIfEmpty}}</td>
<td center title="{{::buy.size}}">{{::buy.size | dashIfEmpty}}</td>
<td center>{{::buy.packing | dashIfEmpty}}</td>
<td center>{{::buy.grouping | dashIfEmpty}}</td>
<td>{{::buy.buyingValue | currency: 'EUR':2}}</td>
<td center title="{{::buy.packagingFk | dashIfEmpty}}">
<vn-autocomplete
vn-one
url="Packagings"
show-field="id"
value-field="id"
where="{isBox: true}"
ng-model="buy.packagingFk">
</vn-autocomplete>
</td>
</tr>
</tbody>
</table>
</vn-horizontal>
</vn-card>
<vn-button-bar>
<vn-submit
label="Import buys">
</vn-submit>
<vn-button
class="cancel"
label="Cancel"
ui-sref="entry.card.buy.index">
</vn-button>
</vn-button-bar>
</div>
</form>
<vn-dialog
vn-id="filterDialog"
message="Filter item">
<tpl-body class="itemFilter">
<vn-horizontal>
<vn-textfield
label="Name"
ng-model="$ctrl.itemFilterParams.name"
ng-keydown="$ctrl.onKeyPress($event)"
vn-focus>
</vn-textfield>
<vn-textfield
label="Size"
ng-model="$ctrl.itemFilterParams.size"
ng-keydown="$ctrl.onKeyPress($event)">
</vn-textfield>
<vn-autocomplete
label="Producer"
ng-model="$ctrl.itemFilterParams.producerFk"
ng-keydown="$ctrl.onKeyPress($event)"
url="Producers"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete
label="Type"
ng-model="$ctrl.itemFilterParams.typeFk"
ng-keydown="$ctrl.onKeyPress($event)"
url="ItemTypes"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete
label="Color"
ng-model="$ctrl.itemFilterParams.inkFk"
ng-keydown="$ctrl.onKeyPress($event)"
url="Inks"
show-field="name"
value-field="id">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal class="vn-mb-md">
<vn-button vn-none
label="Search"
ng-click="$ctrl.filter()">
</vn-button>
</vn-horizontal>
<vn-crud-model
vn-id="itemsModel"
url="Entries/{{$ctrl.$params.id}}/lastItemBuys"
filter="$ctrl.itemFilter"
data="items"
limit="10">
</vn-crud-model>
<vn-data-viewer
model="itemsModel"
class="vn-w-lg">
<vn-table class="scrollable">
<vn-thead>
<vn-tr>
<vn-th shrink>ID</vn-th>
<vn-th expand>Item</vn-th>
<vn-th number>Size</vn-th>
<vn-th expand>Producer</vn-th>
<vn-th>Color</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<a ng-repeat="item in items"
class="clickable vn-tr search-result"
ng-click="$ctrl.selectItem(item.id)">
<vn-td shrink>
<span
vn-click-stop="itemDescriptor.show($event, item.id)"
class="link">
{{::item.id}}
</span>
</vn-td>
<vn-td expand>{{::item.name}}</vn-td>
<vn-td number>{{::item.size}}</vn-td>
<vn-td expand>{{::item.producerName}}</vn-td>
<vn-td>{{::item.inkName}}</vn-td>
</a>
</vn-tbody>
</vn-table>
</vn-data-viewer>
<vn-item-descriptor-popover
vn-id="item-descriptor"
warehouse-fk="$ctrl.vnConfig.warehouseFk">
</vn-item-descriptor-popover>
</tpl-body>
</vn-dialog>

View File

@ -1,159 +0,0 @@
import ngModule from '../../module';
import Section from 'salix/components/section';
import './style.scss';
class Controller extends Section {
constructor($element, $) {
super($element, $);
this.import = {
file: '',
invoice: null,
buys: []
};
}
onFileChange($event) {
const input = $event.target;
const file = input.files[0];
const reader = new FileReader();
reader.onload = event =>
this.fillData(event.target.result);
reader.readAsText(file, 'UTF-8');
}
fillData(raw) {
const data = JSON.parse(raw);
const [invoice] = data.invoices;
this.$.$applyAsync(() => {
this.import.observation = invoice.tx_awb;
const companyName = invoice.tx_company;
const boxes = invoice.boxes;
const buys = [];
for (let box of boxes) {
const boxVolume = box.nu_length * box.nu_width * box.nu_height;
for (let product of box.products) {
const packing = product.nu_stems_bunch * product.nu_bunches;
buys.push({
description: product.nm_product,
companyName: companyName,
size: product.nu_length,
packing: packing,
grouping: product.nu_stems_bunch,
buyingValue: parseFloat(product.mny_rate_stem),
volume: boxVolume,
});
}
}
const boxesId = boxes.map(box => box.id_box);
this.import.ref = boxesId.join(', ');
this.fetchBuys(buys);
});
}
fetchBuys(buys) {
const params = {buys};
const query = `Entries/${this.$params.id}/importBuysPreview`;
this.$http.post(query, params).then(res => {
this.import.buys = res.data;
});
}
onSubmit() {
try {
const params = this.import;
const hasAnyEmptyRow = params.buys.some(buy => {
return buy.itemFk == null;
});
if (hasAnyEmptyRow)
throw new Error(`Some of the imported buys doesn't have an item`);
const query = `Entries/${this.$params.id}/importBuys`;
return this.$http.post(query, params)
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')))
.then(() => this.$state.go('entry.card.buy.index'));
} catch (e) {
this.vnApp.showError(this.$t(e.message));
return false;
}
}
itemSearchFunc($search) {
return /^\d+$/.test($search)
? {id: $search}
: {name: {like: '%' + $search + '%'}};
}
showFilterDialog(buy) {
this.activeBuy = buy;
this.itemFilterParams = {};
this.itemFilter = {
include: [
{
relation: 'producer',
scope: {
fields: ['name']
}
},
{
relation: 'ink',
scope: {
fields: ['name']
}
}
]
};
this.$.filterDialog.show();
}
selectItem(id) {
this.activeBuy['itemFk'] = id;
this.$.filterDialog.hide();
}
filter() {
const filter = this.itemFilter;
const params = this.itemFilterParams;
const where = {};
for (let key in params) {
const value = params[key];
if (!value) continue;
switch (key) {
case 'name':
where[key] = {like: `%${value}%`};
break;
case 'producerFk':
case 'typeFk':
case 'size':
case 'inkFk':
where[key] = value;
}
}
filter.where = where;
this.$.itemsModel.applyFilter(filter);
}
onKeyPress($event) {
if ($event.key === 'Enter')
this.filter();
}
}
Controller.$inject = ['$element', '$scope'];
ngModule.vnComponent('vnEntryBuyImport', {
template: require('./index.html'),
controller: Controller,
bindings: {
worker: '<'
}
});

View File

@ -1,199 +0,0 @@
import './index.js';
describe('Entry', () => {
describe('Component vnEntryBuyImport', () => {
let controller;
let $httpParamSerializer;
let $httpBackend;
beforeEach(ngModule('entry'));
beforeEach(angular.mock.inject(($componentController, $compile, $rootScope, _$httpParamSerializer_, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
$httpParamSerializer = _$httpParamSerializer_;
let $element = $compile('<vn-entry-buy-import-buys></vn-entry-latest-buys')($rootScope);
controller = $componentController('vnEntryBuyImport', {$element});
controller.entry = {
id: 1
};
controller.$params = {id: 1};
}));
describe('fillData()', () => {
it(`should call to the fillData() method`, () => {
controller.fetchBuys = jest.fn();
const rawData = `{
"invoices": [
{
"tx_awb": "123456",
"boxes": [
{
"id_box": 1,
"nu_length": 1,
"nu_width": 15,
"nu_height": 80,
"products": [
{
"nm_product": "Bow",
"nu_length": 1,
"nu_stems_bunch": 1,
"nu_bunches": 1,
"mny_rate_stem": 5.77
}
]
},
{
"id_box": 2,
"nu_length": 25,
"nu_width": 1,
"nu_height": 45,
"products": [
{
"nm_product": "Arrow",
"nu_length": 25,
"nu_stems_bunch": 1,
"nu_bunches": 1,
"mny_rate_stem": 2.16
}
]
}
]
}
]}`;
const expectedBuys = [
{
'buyingValue': 5.77,
'description': 'Bow',
'grouping': 1,
'packing': 1,
'size': 1,
'volume': 1200},
{
'buyingValue': 2.16,
'description': 'Arrow',
'grouping': 1,
'packing': 1,
'size': 25,
'volume': 1125}
];
controller.fillData(rawData);
controller.$.$apply();
const importData = controller.import;
expect(importData.observation).toEqual('123456');
expect(importData.ref).toEqual('1, 2');
expect(controller.fetchBuys).toHaveBeenCalledWith(expectedBuys);
});
});
describe('fetchBuys()', () => {
it(`should perform a query to fetch the buys data`, () => {
const buys = [
{
'buyingValue': 5.77,
'description': 'Bow',
'grouping': 1,
'packing': 1,
'size': 1,
'volume': 1200},
{
'buyingValue': 2.16,
'description': 'Arrow',
'grouping': 1,
'packing': 1,
'size': 25,
'volume': 1125}
];
const query = `Entries/1/importBuysPreview`;
$httpBackend.expectPOST(query).respond(200, buys);
controller.fetchBuys(buys);
$httpBackend.flush();
const importData = controller.import;
expect(importData.buys.length).toEqual(2);
});
});
describe('onSubmit()', () => {
it(`should throw an error when some of the rows doesn't have an item`, () => {
jest.spyOn(controller.vnApp, 'showError');
controller.import = {
observation: '123456',
ref: '1, 2',
buys: [
{
'buyingValue': 5.77,
'description': 'Bow',
'grouping': 1,
'packing': 1,
'size': 1,
'volume': 1200},
{
'buyingValue': 2.16,
'description': 'Arrow',
'grouping': 1,
'packing': 1,
'size': 25,
'volume': 1125}
]
};
controller.onSubmit();
const message = `Some of the imported buys doesn't have an item`;
expect(controller.vnApp.showError).toHaveBeenCalledWith(message);
});
it(`should now perform a query to update columns`, () => {
jest.spyOn(controller.vnApp, 'showSuccess');
controller.$state.go = jest.fn();
controller.import = {
observation: '123456',
ref: '1, 2',
buys: [
{
'itemFk': 10,
'buyingValue': 5.77,
'description': 'Bow',
'grouping': 1,
'packing': 1,
'size': 1,
'volume': 1200},
{
'itemFk': 11,
'buyingValue': 2.16,
'description': 'Arrow',
'grouping': 1,
'packing': 1,
'size': 25,
'volume': 1125}
]
};
const params = controller.import;
const query = `Entries/1/importBuys`;
$httpBackend.expectPOST(query, params).respond(200, params.buys);
controller.onSubmit();
$httpBackend.flush();
const importData = controller.import;
expect(importData.buys.length).toEqual(2);
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.$state.go).toHaveBeenCalledWith('entry.card.buy.index');
});
});
});
});

View File

@ -1,5 +0,0 @@
.itemFilter {
vn-table.scrollable {
height: 500px
}
}

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