Merge branch 'dev' into 8190-entry_getCommission
gitea/salix/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Robert Ferrús 2024-12-16 10:18:53 +00:00
commit e7e6c88ec5
41 changed files with 874 additions and 96 deletions

View File

@ -0,0 +1,112 @@
const UserError = require('vn-loopback/util/user-error');
const axios = require('axios');
module.exports = Self => {
Self.remoteMethod('optimize', {
description: 'Return optimized coords',
accessType: 'READ',
accepts: [{
arg: 'addressIds',
type: 'array',
required: true
}, {
arg: 'firstAddressId',
type: 'number',
required: false
}, {
arg: 'lastAddressId',
type: 'number',
required: false
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/optimize`,
verb: 'GET'
}
});
Self.optimize = async(addressIds, firstAddressId, lastAddressId) => {
const models = Self.app.models;
try {
const osrmConfig = await models.OsrmConfig.findOne();
if (!osrmConfig) throw new UserError(`OSRM service is not configured`);
let coords = [];
if (firstAddressId) {
const address = await models.Address.findById(firstAddressId);
if (address.latitude && address.longitude) {
coords.push({
addressId: address.id,
latitude: address.latitude.toFixed(6),
longitude: address.longitude.toFixed(6)
});
}
}
for (const addressId of addressIds) {
const address = await models.Address.findById(addressId);
if (address.latitude && address.longitude) {
coords.push({
addressId,
latitude: address.latitude.toFixed(6),
longitude: address.longitude.toFixed(6)
});
}
}
if (lastAddressId) {
const firstAddress = await models.Address.findById(lastAddressId);
if (firstAddress.latitude && firstAddress.longitude) {
coords.push({
addressId: firstAddress.id,
latitude: firstAddress.latitude.toFixed(6),
longitude: firstAddress.longitude.toFixed(6)
});
}
}
if (!coords.length) throw new UserError('No address has coordinates');
const concatCoords = coords
.map(coord => `${coord.longitude},${coord.latitude}`)
.join(';');
const response = await axios.post(`
${osrmConfig.url}/trip/v1/driving/${concatCoords}?source=first&destination=last&roundtrip=true
`);
const tolerance = osrmConfig.tolerance;
for (const waypoint of response.data.waypoints) {
const longitude = waypoint.location[0];
const latitude = waypoint.location[1];
const matchedAddress = coords.find(coord =>
coord.position === undefined &&
Math.abs(coord.latitude - latitude) <= tolerance &&
Math.abs(coord.longitude - longitude) <= tolerance
);
if (matchedAddress)
matchedAddress.position = waypoint.waypoint_index;
}
coords.sort((a, b) => {
const posA = a.position !== undefined ? a.position : Infinity;
const posB = b.position !== undefined ? b.position : Infinity;
return posA - posB;
});
return coords;
} catch (err) {
switch (err.response?.data?.code) {
case 'NoTrips':
throw new UserError('No trips found because input coordinates are not connected');
case 'NotImplemented':
throw new UserError('This request is not supported');
case 'InvalidOptions':
throw new UserError('Invalid options or too many coordinates');
default:
throw err;
}
}
};
};

View File

@ -0,0 +1,33 @@
const models = require('vn-loopback/server/server').models;
describe('osrmConfig optimize()', function() {
it('should send coords, receive OSRM response, and return a correctly ordered result', async function() {
const result = await models.OsrmConfig.optimize([4, 3], 1, 2);
// Verifications
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBe(4);
// Check the order
expect(result[0].addressId).toBe(1);
expect(result[1].addressId).toBe(4);
expect(result[2].addressId).toBe(3);
expect(result[3].addressId).toBe(2);
// Check the coordinates format
expect(result[0].latitude).toBe('10.111111');
expect(result[0].longitude).toBe('-74.111111');
});
it('should throw an error if no addresses are provided', async function() {
let error;
try {
await models.OsrmConfig.optimize([], null);
} catch (e) {
error = e;
}
expect(error).toBeDefined();
expect(error.message).toBe('No address has coordinates');
});
});

View File

@ -88,6 +88,9 @@
"Language": {
"dataSource": "vn"
},
"OsrmConfig": {
"dataSource": "vn"
},
"Machine": {
"dataSource": "vn"
},

View File

@ -0,0 +1,4 @@
module.exports = Self => {
require('../methods/osrm-config/optimize')(Self);
};

View File

@ -0,0 +1,24 @@
{
"name": "OsrmConfig",
"base": "VnModel",
"options": {
"mysql": {
"table": "osrmConfig"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"required": true
},
"url": {
"type": "string",
"required": true
},
"tolerance": {
"type": "number",
"required": false
}
}
}

View File

@ -2128,7 +2128,7 @@ INSERT INTO `ACL` VALUES (746,'Claim','getSummary','READ','ALLOW','ROLE','claimV
INSERT INTO `ACL` VALUES (747,'CplusRectificationType','*','READ','ALLOW','ROLE','administrative',NULL);
INSERT INTO `ACL` VALUES (748,'SiiTypeInvoiceOut','*','READ','ALLOW','ROLE','salesPerson',NULL);
INSERT INTO `ACL` VALUES (749,'InvoiceCorrectionType','*','READ','ALLOW','ROLE','salesPerson',NULL);
INSERT INTO `ACL` VALUES (750,'InvoiceOut','transferInvoice','WRITE','ALLOW','ROLE','administrative',NULL);
INSERT INTO `ACL` VALUES (750,'InvoiceOut','transfer','WRITE','ALLOW','ROLE','administrative',NULL);
INSERT INTO `ACL` VALUES (751,'Application','executeProc','*','ALLOW','ROLE','employee',NULL);
INSERT INTO `ACL` VALUES (752,'Application','executeFunc','*','ALLOW','ROLE','employee',NULL);
INSERT INTO `ACL` VALUES (753,'NotificationSubscription','getList','READ','ALLOW','ROLE','employee',NULL);

View File

@ -428,10 +428,10 @@ INSERT INTO `vn`.`clientConfig`(`id`, `riskTolerance`, `maxCreditRows`, `maxPric
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`)
VALUES
(1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 1),
(2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 1),
(3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 1),
(4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, NULL, NULL, 0, 1),
(1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, -74.1111111, 10.1111111, 0, 1),
(2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, -74.2222222, 10.2222222, 0, 1),
(3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, -74.3333333, 10.3333333, 0, 1),
(4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, -74.4444444, 10.4444444, 0, 1),
(5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1),
(6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1),
(7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1),
@ -462,7 +462,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(120, 'Somewhere in Montortal', 'address 20', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0),
(121, 'the bat cave', 'address 21', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 0),
(122, 'NY roofs', 'address 22', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 0),
(123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 0),
(123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, -74.555555, 10.555555, 0, 0),
(124, 'Stark tower Gotham', 'address 24', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1104, 2, NULL, NULL, 0, 0),
(125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0),
(126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0),
@ -1520,17 +1520,18 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`, `typeFk`)
VALUES
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, '', 'packaging'),
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two', 'product'),
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, '', 'packaging'),
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two' , 'product'),
(3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three', 'product'),
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four', 'product'),
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five', 'product'),
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six', 'product'),
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four' , 'product'),
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five' , 'product'),
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six' , 'product'),
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven', 'product'),
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, '', 'product'),
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, '', 'product'),
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, '', 'product'),
(99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99', 0, '', 'product');
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, '', 'product'),
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, '', 'product'),
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10',1, '', 'product'),
(11, 4, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 11',0, '', 'product'),
(99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99',0, '', 'product');
INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`)
VALUES (2, 4, 1);
@ -1570,7 +1571,8 @@ INSERT INTO `bs`.`waste`(`buyerFk`, `year`, `week`, `itemFk`, `itemTypeFk`, `sal
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 4, util.VN_CURDATE()),
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 7.30, 7.00, 0, 1, 0, 4, util.VN_CURDATE()),
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()),
(16, 99,1,50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, '2024-07-30 08:13:51.000');
(16, 99,1,50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, '2024-07-30 08:13:51.000'),
(17, 11, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH);
INSERT INTO `hedera`.`order`(`id`, `date_send`, `customer_id`, `delivery_method_id`, `agency_id`, `address_id`, `company_id`, `note`, `source_app`, `confirmed`,`total`, `date_make`, `first_row_stamp`, `confirm_date`)
VALUES
@ -4035,3 +4037,10 @@ INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel)
INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate)
VALUES (1106,'26493101E','2019-09-20');
INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance)
VALUES (1,'https://router.project-osrm.org', 0.002);
INSERT IGNORE INTO vn.inventoryConfig
SET id = 1,
supplierFk = 4;

View File

@ -25,7 +25,7 @@ BEGIN
DECLARE vIsInformativeExportation BOOL DEFAULT FALSE;
DECLARE vCursor CURSOR FOR
SELECT it.taxableBase,
SELECT SUM(it.taxableBase),
CAST(SUM((( it.taxableBase / 100) * t.PorcentajeIva)) AS DECIMAL (10,2)),
t.PorcentajeIva,
it.transactionTypeSageFk,

View File

@ -46,7 +46,7 @@ BEGIN
JOIN claimDestination cd ON cd.id = ce.claimDestinationFk
JOIN claim c ON c.id = ce.claimFk
JOIN claimState cs ON cs.id = c.claimStateFk
WHERE cd.description NOT IN ('Bueno', 'Corregido')
WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim')
AND NOT ce.isGreuge
AND cs.code = 'resolved';
@ -71,7 +71,7 @@ BEGIN
JOIN claimDestination cd ON cd.id = ce.claimDestinationFk
JOIN claim c ON c.id = ce.claimFk
JOIN claimState cs ON cs.id = c.claimStateFk
WHERE cd.description NOT IN ('Bueno', 'Corregido')
WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim')
AND NOT ce.isGreuge
AND cs.code = 'resolved'
AND c.isChargedToMana;
@ -82,7 +82,7 @@ BEGIN
JOIN claim c ON c.id = ce.claimFk
JOIN claimState cs ON cs.id = c.claimStateFk
SET ce.isGreuge = TRUE
WHERE cd.description NOT IN ('Bueno', 'Corregido')
WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim')
AND NOT ce.isGreuge
AND cs.code = 'resolved';
@ -161,7 +161,7 @@ BEGIN
JOIN claimDestination cd ON cd.id = ce.claimDestinationFk
JOIN claim c ON c.id = ce.claimFk
JOIN claimState cs ON cs.id = c.claimStateFk
WHERE cd.description NOT IN ('Bueno', 'Corregido')
WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim')
AND cs.code = 'resolved'
AND c.ticketCreated >= util.VN_CURDATE() - INTERVAL 1 YEAR
GROUP BY c.clientFk

View File

@ -10,8 +10,8 @@ BEGIN
* @param vIsRaid idRaid value
* @param vDaysInForward daysInForward value
*/
IF (NOT vIsRaid AND vDaysInForward IS NOT NULL) OR (vIsRaid AND vDaysInForward IS NULL) THEN
CALL util.throw('The raid information is not correct');
IF NOT vIsRaid AND vDaysInForward THEN
CALL util.throw('If daysInForward has a value, the raid cannot be unchecked');
END IF;
END$$
DELIMITER ;

View File

@ -8,22 +8,15 @@ BEGIN
DECLARE vDone BOOL DEFAULT FALSE;
DECLARE vBuyerEmail VARCHAR(40);
DECLARE vTravelLink TEXT;
DECLARE vMailBody TEXT DEFAULT '';
DECLARE vMailBody TEXT;
DECLARE vDaysBetweenDates INT;
DECLARE vSubject VARCHAR(30);
DECLARE vCur CURSOR FOR
SELECT GROUP_CONCAT(DISTINCT
CONCAT('https://salix.verdnatura.es/#!/travel/',
ttm.travelFk,
'/summary ')
ORDER BY ttm.travelFk SEPARATOR '\n\r') travelLink,
CONCAT(u.name, '@verdnatura.es') buyerEmail
FROM tTravelToMove ttm
JOIN entry e ON e.travelFk = ttm.travelFk
JOIN buy b ON b.entryFk = e.id
JOIN item i ON i.id = b.itemFk
JOIN itemType it ON it.id = i.typeFk
JOIN account.user u ON u.id = it.workerFk
GROUP BY u.name;
DECLARE vTravels CURSOR FOR
SELECT GROUP_CONCAT(DISTINCT travelLink ORDER BY id SEPARATOR '\n\r'),
buyerEmail
FROM tTravelToMove
GROUP BY buyerEmail;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
@ -34,35 +27,50 @@ BEGIN
END;
CREATE OR REPLACE TEMPORARY TABLE tTravelToMove
SELECT id travelFk,
util.VN_CURDATE() + INTERVAL daysInForward DAY newLanded
FROM travel
WITH travels AS (
SELECT id,
CONCAT('https://salix.verdnatura.es/#!/travel/', id,'/summary') travelLink,
util.VN_CURDATE() + INTERVAL daysInForward DAY newLanded,
util.VN_CURDATE() - INTERVAL DATEDIFF(landed, shipped) + daysInForward DAY newShipped
FROM vn.travel
WHERE isRaid
AND daysInForward;
AND daysInForward
)SELECT t.id,
t.travelLink,
t.newLanded,
t.newShipped,
CONCAT(u.name, '@verdnatura.es') buyerEmail
FROM travels t
STRAIGHT_JOIN vn.entry e ON e.travelFk = t.id
JOIN vn.buy b ON b.entryFk = e.id
JOIN vn.item i ON i.id = b.itemFk
JOIN vn.itemType it ON it.id = i.typeFk
JOIN account.user u ON u.id = it.workerFk
GROUP BY t.id;
START TRANSACTION;
UPDATE travel tr
JOIN tTravelToMove ttm ON ttm.travelFk = tr.id
SET tr.landed = ttm.newLanded;
JOIN tTravelToMove ttm ON ttm.id = tr.id
SET tr.landed = ttm.newLanded,
tr.shipped = ttm.newShipped;
OPEN vCur;
OPEN vTravels;
l: LOOP
SET vDone = FALSE;
FETCH vCur INTO vTravelLink, vBuyerEmail;
FETCH vTravels INTO vTravelLink, vBuyerEmail;
IF vDone THEN
LEAVE l;
END IF;
CALL `vn`.`mail_insert`(
vBuyerEmail,
'noreply@verdnatura.es',
'Cambio de fecha en Redadas',
CONCAT('Se ha movido los siguientes travels: \n\r ', vTravelLink));
SET vSubject = 'Cambio de fecha en Redadas',
vMailBody = CONCAT('Se ha movido los siguientes travels: \n\r ', vTravelLink);
CALL mail_insert(vBuyerEmail, 'noreply@verdnatura.es', vSubject, vMailBody);
END LOOP;
CLOSE vCur;
CLOSE vTravels;
COMMIT;
DROP TEMPORARY TABLE tTravelToMove;
END$$

View File

@ -20,6 +20,10 @@ BEGIN
CALL travel_checkWarehouseIsFeedStock(NEW.warehouseInFk);
END IF;
IF NOT (NEW.isRaid <=> OLD.isRaid) OR NOT (NEW.daysInForward <=> OLD.daysInForward) THEN
CALL travel_checkRaid(NEW.isRaid, NEW.daysInForward);
END IF;
IF NOT (NEW.awbFk <=> OLD.awbFk)THEN
SELECT COUNT(*) INTO vHasAnyInvoiceBooked
FROM travel t

View File

@ -0,0 +1,185 @@
CREATE TABLE IF NOT EXISTS `vn`.`sim` (
`code` VARCHAR(25) COMMENT 'No se ha puesto BIGINT por incompatibilidad con Access',
`line` VARCHAR(15) NOT NULL CHECK (`line` REGEXP '^[0-9]+$'),
`ext` INT(4) NOT NULL,
`pin` INT(4) NOT NULL,
`puk` INT(15) NOT NULL,
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
ALTER TABLE vn.deviceProductionUser CHANGE simSerialNumber simFk VARCHAR(25) DEFAULT NULL NULL;
ALTER TABLE vn.deviceProductionUser MODIFY COLUMN simFk VARCHAR(25) DEFAULT NULL NULL;
INSERT IGNORE INTO `vn`.`sim` (`line`, `ext`, `pin`, `code`, `puk`) VALUES
('621188151', 2209, 1486, '3456985220092508',14213470),
('621188152', 2210, 8765, '3456985220092509',99473093),
('621188153', 2211, 3064, '3456985220092510',52967210),
('621188759', 2081, 3700, '3456985220123637',56600999),
('621188760', 2082, 3259, '345698522023638',87492404),
('621188761', 2083, 2790, '3456985220123639',94009456),
('621188762', 2084, 2480, '3456985220123644',1484999),
('621188763', 2085, 6876, '3456985220123641',36577064),
('621188766', 2086, 7775, '3456985220123642',80761698),
('621188769', 2088, 4027, '3456985220123643',37921712),
('621188771', 2089, 8797, '3456985220123640',63092540),
('621188772', 2090, 8404, '3456985220123645',21014997),
('621188773', 2091, 5481, '3456985220123646',16317277),
('621188774', 2092, 9632, '3456985220123647',22235994),
('621188775', 2093, 4654, '3456985220123648',28506486),
('621188838', 2094, 1392, '3456985220123649',29498627),
('621188839', 2095, 7774, '3456985220123650',46263490),
('621188840', 2096, 7304, '3456985220123658',8212044),
('621188841', 2097, 5569, '3456985220123652',81597658),
('621188842', 2098, 4944, '3456985220123653',24961501),
('621188843', 2099, 5142, '3456985220123654',17035634),
('621188844', 2111, 7245, '3456985220123655',90231951),
('621188846', 2110, 6590, '3456985220123656',72201537),
('667680207', 2564, 4042, '34569832200759166',48401979),
('667680315', 2565, 7143, '34569832200759372',32143252),
('667680318', 2566, 6342, '34569832200759364',39597112),
('667680413', 2567, 5580, '34569832200759356',32786992),
('667680463', 2568, 0171, '34569832200759349',34240853),
('667688217', 2569, 2500, '34569832200759331',5687589),
('633603945', 2212, 7129, '34569832200759323',51554019),
('622130186', 2213, 4826, '34569832200759307',19623551),
('633973424', 2214, 8535, '34569832200759299',94619307),
('633703828', 2215, 8628, '34569832200759281',22468012),
('622025110', 2216, 2399, '34569832200759273',34602918),
('622924867', 2217, 5665, '34569832200759265',26920216),
('722409630', 2218, 5211, '34569832200759240',93750137),
('623590529', 2219, 0493, '34569832200759208',47077088),
('633243462', 2220, 6902, '34569832200759174',6421962),
('633047286', 2221, 5592, '34569832200759182',32069439),
('744716801', 2112, 9184, '34569832200759190',57049814),
('655995021', 2131, 8896, '34569852202049093',19497356),
('685522718', 2132, 1955, '34569852202049101',28519879),
('674587213', 2994, 2006, '34569332200223743',62360135),
('674587227', 2993, 9271, '34569332200223750',81628192),
('674587229', 2993, 0900, '34569332200223768',91119071),
('674587231', 2992, 5007, '34569332200223776',45826232),
('674587234', 2991, 1378, '34569332200223784',91245744),
('674587240', 2990, 0905, '34569332200223792',13083224),
('674587245', 2989, 9059, '34569332200223800',15291807),
('674587250', 2988, 8188, '34569332200223818',83017918),
('674587254', 2987, 2962, '34569332200223826',92809271),
('674587256', 2986, 0358, '34569332200223834',81067040),
('674592713', 2570, 2537, '34569332200230672',82325850),
('697832478', 2579, 0936, '34568732200494825',49658372),
('697832176', 2571, 5944, '34568732200494742',19039461),
('697832477', 2572, 5138, '34568732200494759',25712504),
('697832178', 2573, 4597, '34568732200494767',66241760),
('697832182', 2574, 9241, '34568732200494775',07342562),
('697832196', 2575, 2995, '34568732200494783',53929026),
('697832214', 2576, 7434, '34568732200494791',49698432),
('697832230', 2577, 7004, '34568732200494809',21578612),
('697832235', 2578, 9674, '34568732200494817',93090700),
('673420375', 2599, 5430, '34562052300117259',35911412),
('673420367', 2598, 8402, '34562052300117242',924654),
('673420361', 2597, 5125, '34562052300117234',12027970),
('673420355', 2596, 5069, '34562052300117226',34978149),
('673420348', 2595, 8911, '34562052300117218',4228121),
('673420346', 2594, 2461, '34562052300117200',67670772),
('673420345', 2593, 2226, '34562052300117192',90586404),
('673420306', 2592, 3355, '34562052300117184',97850017),
('673420257', 2591, 9395, '34562052300117176',50713786),
('673420231', 2590, 1378, '34562052300117168',50151763),
('673420223', 2589, 9580, '34562052300117150',99534550),
('673420216', 2588, 4955, '34562052300117143',317554),
('673420203', 2587, 6742, '34562052300117135',69321531),
('673420201', 2586, 1659, '34562052300117127',54720480),
('673420199', 2585, 7823, '34562052300117119',22923796),
('673420198', 2584, 1787, '34562052300117101',54414630),
('673420168', 2583, 6334, '34562052300117093',50694894),
('673420147', 2582, 8951, '34562052300117085',1402535),
('673420125', 2581, 3068, '34562052300117077',86216200),
('673420124', 2580, 9517, '34562052300117069',42504099),
('600294609', 2715, 7474, '34569832304894588',55923317),
('600084713', 2703, 8342, '34569832304894570',8392636),
('600084732', 2704, 1625, '34569832304894513',75477452),
('600084850', 2705, 9896, '34569832304894653',28589813),
('600084951', 2706, 5520, '34569832304894661',75353012),
('600084978', 2707, 2698, '34569832304894679',9005523),
('600085403', 2708, 0837, '34569832304894646',77051152),
('600085513', 2709, 3106, '34569832304894687',41571002),
('600293916', 2712, 8990, '34569832304894620',95188676),
('600294160', 2714, 6376, '34569832304894703',79879896),
('671919529', 2975, 9184, '34569832304806236',7535392),
('671919942', 2981, 0328, '34569832304806269',31052894),
('671919530', 2976, 0344, '34569832304806251',89860304),
('671919533', 2977, 0668, '34569832304806244',42921771),
('671919535', 2978, 0105, '34569832304806277',31009417),
('671919537', 2979, 0881, '34569832304806285',33479769),
('671919540', 2980, 9874, '34569832304806293',14103929),
('671919525', 2972, 2089, '34569832304806301',45903729),
('671919527', 2973, 8206, '34569832304806368',1586035),
('671919528', 2974, 2532, '34569832304806327',62310124),
('673668717', 2836, 7973, '34562032301044223',15635496),
('673668734', 2837, 4457, '34562032301044231',18313118),
('673668738', 2824, 2911, '34562032301044249',30875583),
('673668745', 2838, 7253, '34562032301044256',62754222),
('673668796', 2839, 0068, '34562032301044264',15556829),
('673668803', 2840, 2386, '34562032301044272',17572287),
('673669591', 2850, 3833, '34562032301044280',34828896),
('673668808', 2841, 3584, '34562032301044298',16234497),
('673670102', 2851, 3554, '34562032301044306',23652625),
('673670131', 2852, 4412, '34562032301044314',88611709),
('673670135', 2827, 6058, '34562032301044322',53918579),
('673670201', 2828, 8066, '34562032301044330',92369343),
('673670225', 2829, 4592, '34562032301044348',24126635),
('673670236', 2830, 2974, '34562032301044355',88608465),
('673671485', 2849, 0349, '34562032301044363',44944874),
('673461977', 2871, 1728, '34562032400157090',46975780),
('673461975', 2870, 4734, '34562032400157082',69628432),
('673461972', 2867, 6276, '34562032400157058',53338365),
('673461979', 2872, 6043, '34562032400157108',36525197),
('673461958', 2859, 3164, '34562032400156977',58947831),
('673461957', 2857, 8685, '34562032400156969',15826386),
('673461944', 2853, 1073, '34562032400156910',20452195),
('673461974', 2869, 7121, '34562032400157074',32044645),
('673461973', 2868, 8022, '34562032400157066',29282044),
('673461971', 2866, 3089, '34562032400157041',66149978),
('673461969', 2865, 7555, '34562032400157033',78391293),
('673461960', 2860, 5203, '34562032400156985',37138232),
('673461952', 2855, 6915, '34562032400156936',62724661),
('673461949', 2854, 8706, '34562032400156928',5594345),
('673461966', 2863, 2496, '34562032400157017',93450666),
('673461968', 2864, 3703, '34562032400157025',23208841),
('673461963', 2862, 9364, '34562032400157009',29712130),
('673462719', 2873, 9387, '34562032400156951',50434348),
('673461962', 2861, 8441, '34562032400156993',39686909),
('673461956', 2826, 5392, '34562032400156944',5496107),
('673465284', 2694, 1523, '34562032400171349',14554994),
('673465282', 2692, 4645, '34562032400171323',24871187),
('673465283', 2693, 5253, '34562032400171331',28303238),
('673465841', 2696, 0849, '34562032400171257',21673222),
('673465258', 2679, 4140, '34562032400171174',39793881),
('673465263', 2680, 6922, '34562032400171182',12253261),
('673465265', 2681, 9112, '34562032400171190',93894366),
('673465267', 2682, 3259, '34562032400171208',2342189),
('673465268', 2683, 8540, '34562032400171216',63886925),
('673465285', 2695, 4167, '34562032400171356',79227618),
('673465270', 2684, 4292, '34562032400171224',19216349),
('673465272', 2685, 4007, '34562032400171232',14396903),
('673465273', 2686, 6894, '34562032400171240',13569394),
('673465274', 2687, 5268, '34562032400171265',59453667),
('673465275', 2688, 0232, '34562032400171273',62324713),
('673465276', 2689, 2720, '34562032400171281',65977200),
('673465843', 2698, 4773, '34562032400171364',78387158),
('673465842', 2697, 3729, '34562032400171315',94201789),
('673465280', 2691, 0503, '34562032400171307',12298533),
('673465279', 2690, 8239, '34562032400171299',76183877);
UPDATE vn.deviceProductionUser
SET simFk = NULL
WHERE id IN (
SELECT dpu.id
FROM vn.deviceProductionUser dpu
LEFT JOIN vn.sim s ON s.code = dpu.simFk
WHERE s.code IS NULL
AND dpu.simFk IS NOT NULL
);
ALTER TABLE vn.deviceProductionUser ADD CONSTRAINT deviceProductionUser_sim_FK
FOREIGN KEY (simFk) REFERENCES vn.sim(code) ON DELETE RESTRICT ON UPDATE CASCADE;
GRANT SELECT, INSERT, DELETE, UPDATE ON TABLE vn.sim TO hr;

View File

@ -0,0 +1,3 @@
-- Place your SQL code here
INSERT IGNORE INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
VALUES('InventoryConfig', 'find', 'READ', 'ALLOW', 'ROLE', 'buyer');

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.`zone` MODIFY COLUMN `price` DECIMAL(10,2);

View File

@ -0,0 +1,20 @@
CREATE TABLE `vn`.`osrmConfig` (
`id` int(10) unsigned NOT NULL,
`url` varchar(100) NOT NULL COMMENT 'Dirección base de la API',
`tolerance` decimal(6,6) NOT NULL DEFAULT 0 COMMENT 'Tolerancia entre las coordenadas enviadas y las retornadas',
PRIMARY KEY (`id`),
CONSTRAINT `osrmConfig_check` CHECK (`id` = 1)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
-- Para que no de error al añadir la FK de zone
UPDATE vn.zone
SET price = 0.1
WHERE price = 0;
ALTER TABLE vn.`zone`
ADD addressFk int(11) DEFAULT NULL COMMENT 'Punto de distribución de donde salen para repartir',
ADD CONSTRAINT zone_address_FK FOREIGN KEY (addressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE vn.zoneConfig
ADD defaultAddressFk int(11) DEFAULT NULL NULL COMMENT 'Punto de distribución por defecto',
ADD CONSTRAINT zoneConfig_address_FK FOREIGN KEY (defaultAddressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,5 @@
INSERT IGNORE INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('OsrmConfig','optimize','READ','ALLOW','ROLE','employee'),
('Route', 'optimizePriority','*','ALLOW','ROLE','employee');
INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance)
VALUES (1,'https://router.project-osrm.org', 0.002);

View File

@ -247,5 +247,7 @@
"The raid information is not correct": "The raid information is not correct",
"Payment method is required": "Payment method is required",
"Sales already moved": "Sales already moved",
"Holidays to past days not available": "Holidays to past days not available"
"Holidays to past days not available": "Holidays to past days not available",
"There are tickets to be invoiced": "There are tickets to be invoiced for this zone, please delete them first",
"Price cannot be blank": "Price cannot be blank"
}

View File

@ -388,10 +388,15 @@
"You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada",
"ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}",
"The web user's email already exists": "El correo del usuario web ya existe",
"Sales already moved": "Ya han sido transferidas",
"The raid information is not correct": "La información de la redada no es correcta",
"There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero",
"Sales already moved": "Ya han sido transferidas",
"The raid information is not correct": "La información de la redada no es correcta",
"There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero",
"No trips found because input coordinates are not connected": "No se encontraron rutas porque las coordenadas de entrada no están conectadas",
"This request is not supported": "Esta solicitud no es compatible",
"Invalid options or too many coordinates": "Opciones invalidas o demasiadas coordenadas",
"No address has coordinates": "Ninguna dirección tiene coordenadas",
"An item type with the same code already exists": "Un tipo con el mismo código ya existe",
"Holidays to past days not available": "Las vacaciones a días pasados no están disponibles"
"Holidays to past days not available": "Las vacaciones a días pasados no están disponibles",
"All tickets have a route order": "Todos los tickets tienen orden de ruta",
"Price cannot be blank": "Price cannot be blank"
}

View File

@ -72,6 +72,14 @@ module.exports = function(Self) {
{
arg: 'isLogifloraAllowed',
type: 'boolean'
},
{
arg: 'longitude',
type: 'any',
},
{
arg: 'latitude',
type: 'any',
}
],
returns: {

View File

@ -38,8 +38,9 @@ describe('Entry filter()', () => {
};
const result = await models.Entry.filter(ctx, options);
const resultWithCurrency = result.filter(entry => entry.currencyFk === 1);
expect(result.length).toEqual(12);
expect(result.length).toEqual(resultWithCurrency.length);
await tx.rollback();
} catch (e) {
@ -141,18 +142,21 @@ describe('Entry filter()', () => {
it('should return the entry matching the company', async() => {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
const companyFk = 442;
try {
const ctx = {
args: {
companyFk: 442
companyFk
},
req: {accessToken: {userId: 9}}
};
const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(11);
const resultWithCurrency = result.filter(entry => entry.companyFk === companyFk);
expect(result.length).toEqual(resultWithCurrency.length);
await tx.rollback();
} catch (e) {

View File

@ -28,5 +28,8 @@
},
"StockBought": {
"dataSource": "vn"
},
"InventoryConfig": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,18 @@
{
"name": "InventoryConfig",
"base": "VnModel",
"options": {
"mysql": {
"table": "inventoryConfig"
}
},
"properties": {
"id": {
"type": "number",
"id": true
},
"supplierFk": {
"type": "number"
}
}
}

View File

@ -54,7 +54,8 @@ module.exports = Self => {
b.packageValue,
b.packagingFk ,
s.id AS supplierFk,
s.name AS supplier
s.name AS supplier,
b.printedStickers
FROM itemType it
RIGHT JOIN (entry e
LEFT JOIN supplier s ON s.id = e.supplierFk

View File

@ -34,10 +34,31 @@ describe('item lastEntriesFilter()', () => {
const options = {transaction: tx};
try {
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
const itemFk = 1;
const filter = {where: {itemFk, landed: {between: [minDate, maxDate]}}};
const result = await models.Item.lastEntriesFilter(filter, options);
const minDateUtc = new Date(minDate).getTime();
const maxDateUtc = new Date(maxDate).getTime();
expect(result.length).toEqual(6);
const resultMatch = (
await Promise.all(
result.map(async item => {
const itemRecord = await models.Buy.findOne({
fields: ['id'],
where: {id: item.id},
options,
});
const isItemFkValid = itemRecord?.id === itemFk;
const landedDate = new Date(item.landed).getTime();
const isLandedValid = landedDate >= minDateUtc && landedDate <= maxDateUtc;
return isItemFkValid && isLandedValid;
})
)
).filter(Boolean).length;
expect(result.length).toEqual(resultMatch);
await tx.rollback();
} catch (e) {

View File

@ -89,6 +89,11 @@ module.exports = Self => {
type: 'number',
description: `The alert level of the tickets`
},
{
arg: 'packing',
type: 'string',
description: `The packing of the items`
},
{
arg: 'countryFk',
type: 'number',
@ -174,7 +179,7 @@ module.exports = Self => {
stmt = new ParameterizedSQL(`
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
(PRIMARY KEY (id))
ENGINE = MEMORY
ENGINE = InnoDB
SELECT t.id,
t.shipped,
CAST(DATE(t.shipped) AS CHAR) shippedDate,
@ -200,10 +205,18 @@ module.exports = Self => {
u.name userName,
c.salesPersonFk,
c.credit,
pm.name payMethod,
z.hour zoneLanding,
z.name zoneName,
z.id zoneFk,
st.classColor,
d.id departmentFk,
d.name department,
(SELECT GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk SEPARATOR ',')
FROM sale s
JOIN item i ON i.id = s.itemFk
WHERE s.ticketFk = t.id
) AS packing,
TIME_FORMAT(t.shipped, '%H:%i') preparationHour,
TIME_FORMAT(z.hour, '%H:%i') theoreticalhour,
TIME_FORMAT(zed.etc, '%H:%i') practicalHour
@ -217,7 +230,10 @@ module.exports = Self => {
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
LEFT JOIN state st ON st.id = ts.stateFk
LEFT JOIN client c ON c.id = t.clientFk
LEFT JOIN payMethod pm ON pm.id = c.payMethodFk
LEFT JOIN worker wk ON wk.id = c.salesPersonFk
LEFT JOIN workerDepartment wd ON wd.workerFk = wk.id
LEFT JOIN department d ON d.id = wd.departmentFk
LEFT JOIN account.user u ON u.id = wk.id
LEFT JOIN (
SELECT zoneFk,
@ -362,6 +378,7 @@ module.exports = Self => {
}
case 'agencyModeFk':
case 'warehouseFk':
case 'packing':
case 'countryFk':
param = `f.${param}`;
return {[param]: value};

View File

@ -0,0 +1,122 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('optimizePriority', {
description: 'Updates the ticket priority of tickets without priority',
accepts: {
arg: 'id',
type: 'number',
required: true,
description: 'Route id',
http: {source: 'path'}
},
returns: {
type: 'object',
root: true
},
http: {
path: '/:id/optimizePriority',
verb: 'POST'
}
});
Self.optimizePriority = async(id, options) => {
const models = Self.app.models;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
const tickets = await models.Ticket.find({
where: {routeFk: id}
}, myOptions);
let ticketAddress = [];
for (const ticket of tickets) {
ticketAddress.push({
ticketId: ticket.id,
addressId: ticket.addressFk,
zoneId: ticket.zoneFk,
priority: ticket.priority
});
}
// Igualamos los priority del mismo addressId
const addressPriorityMap = ticketAddress.reduce((acc, {addressId, priority}) => {
if (priority !== null) {
acc[addressId] = acc[addressId] === undefined
? priority
: Math.max(acc[addressId], priority);
}
return acc;
});
ticketAddress.forEach(item => {
const maxPriority = addressPriorityMap[item.addressId];
if (maxPriority) item.priority = maxPriority;
});
// Añadimos las direcciones a optimizar
let addressIds = [];
ticketAddress.forEach(h => {
if (!addressIds.includes(h.addressId) && !h.priority)
addressIds.push(h.addressId);
});
if (!addressIds.length) throw new UserError('All tickets have a route order');
// Obtenemos el zoneId más frecuente
const zoneFrequency = ticketAddress.reduce((acc, {zoneId}) => {
if (zoneId != null) acc[zoneId] = (acc[zoneId] || 0) + 1;
return acc;
}, {});
const [mostFrequentZoneId] = Object.entries(zoneFrequency)
.reduce((maxEntry, entry) => entry[1] > maxEntry[1] ? entry : maxEntry, [null, 0]);
// Obtenemos los address inicio y fin
const maxPosition = Math.max(...ticketAddress.map(g => g.priority));
let firstAddress = (await models.Zone.findById(mostFrequentZoneId, myOptions))?.addressFk
|| (await models.ZoneConfig.findOne())?.defaultAddressFk;
const lastAddress = firstAddress;
if (maxPosition) firstAddress = ticketAddress.find(g => g.priority === maxPosition)?.addressId;
// Revisamos las coincidencias y actualizamos la prioridad en el array
const addressPositions = await models.OsrmConfig.optimize(addressIds, firstAddress, lastAddress, myOptions);
await Promise.all(ticketAddress.map(async i => {
const foundPosition = addressPositions.find(item => item.addressId === i.addressId);
if (foundPosition) i.priority = foundPosition.position + (maxPosition + 1);
}));
// Suavizado de prioridad para que no hayan escalones
const allPriorities = ticketAddress
.map(item => item.priority)
.filter(p => p !== null);
const uniquePriorities = [...new Set(allPriorities)].sort((a, b) => a - b);
const priorityMap = {};
uniquePriorities.forEach((p, index) => {
priorityMap[p] = index + 1;
});
ticketAddress.forEach(item => {
if (item.priority !== null) item.priority = priorityMap[item.priority];
});
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
// Realizamos el update en la base de datos
try {
await Promise.all(ticketAddress.map(async y => {
if (y.priority) {
const ticket = await models.Ticket.findById(y.ticketId);
await ticket.updateAttribute('priority', y.priority, myOptions);
}
}));
if (tx) await tx.commit();
return;
} catch (err) {
if (tx) await tx.rollback();
throw err;
}
};
};

View File

@ -0,0 +1,36 @@
const models = require('vn-loopback/server/server').models;
const routeId = 1;
describe('route optimizePriority())', function() {
it('should execute without throwing errors', async function() {
const tx = await models.Route.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await models.Ticket.updateAll(
{routeFk: routeId},
{priority: null},
options
);
await models.Route.optimizePriority(routeId, options);
await tx.rollback();
} catch (e) {
error = e;
await tx.rollback();
}
expect(error).toBeUndefined();
});
it('should execute with error', async function() {
let error;
try {
await models.Route.optimizePriority(routeId);
} catch (e) {
error = e;
}
expect(error).toBeDefined();
expect(error.message).toBe('All tickets have a route order');
});
});

View File

@ -16,4 +16,5 @@ module.exports = Self => {
require('../methods/route/downloadZip')(Self);
require('../methods/route/getExpeditionSummary')(Self);
require('../methods/route/getByWorker')(Self);
require('../methods/route/optimizePriority')(Self);
};

View File

@ -49,7 +49,8 @@ module.exports = Self => {
es.workerFk expeditionScanWorkerFk,
su.name scannerUserName,
es.scanned,
est.description state
est.description state,
de.longName
FROM vn.expedition e
LEFT JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk
INNER JOIN vn.item i1 ON i1.id = e.freightItemFk
@ -59,6 +60,7 @@ module.exports = Self => {
LEFT JOIN account.user u ON u.id = e.workerFk
LEFT JOIN vn.expeditionScan es ON es.expeditionFk = e.id
LEFT JOIN account.user su ON su.id = es.workerFk
LEFT JOIN dipole.expedition_PrintOut de ON de.expeditionFk = e.id
) e
`);
stmt.merge(conn.makeWhere(filter.where));

View File

@ -82,7 +82,7 @@ module.exports = Self => {
const message = $t('Changed sale quantity', {
ticketId: sale.ticket().id,
changes: change,
changes: JSON.stringify(change),
ticketUrl: `${url}ticket/${sale.ticket().id}/sale`,
});

View File

@ -64,6 +64,11 @@ module.exports = Self => {
arg: 'myTeam',
type: 'boolean',
description: `Team partners`
},
{
arg: 'daysOnward',
type: 'number',
description: 'The days onward'
}
],
returns: {
@ -104,6 +109,9 @@ module.exports = Self => {
teamMembersId.push(userId);
}
const today = Date.vnNew();
const future = Date.vnNew();
let where = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
@ -140,9 +148,13 @@ module.exports = Self => {
return {'tr.requesterFk': {inq: teamMembersId}};
else
return {'tr.requesterFk': {nin: teamMembersId}};
case 'daysOnward':
today.setHours(0, 0, 0, 0);
future.setDate(today.getDate() + value);
future.setHours(23, 59, 59, 999);
return {'t.shipped': {between: [today, future]}};
}
});
if (!where)
where = {};
where['tw.ticketFk'] = null;

View File

@ -3,9 +3,10 @@ const models = require('vn-loopback/server/server').models;
describe('travel getEntries()', () => {
const travelId = 1;
it('should check the response contains the id', async() => {
const entries = await models.Travel.getEntries(travelId);
const result = await models.Travel.getEntries(travelId);
const entries = await models.Entry.find({where: {travelFk: travelId}});
expect(entries.length).toEqual(1);
expect(entries.length).toEqual(result.length);
expect(entries[0].id).toEqual(1);
});

View File

@ -23,7 +23,7 @@
"type" : "number"
},
"isDependend": {
"type" : "number"
"type" : "boolean"
},
"familySituation": {
"type" : "number"
@ -35,15 +35,17 @@
"type" : "number"
},
"hasHousingPaymentBefore": {
"type" : "number"
"type" : "boolean"
},
"hasHousingPaymentAfter": {
"type" : "number"
"type" : "boolean"
},
"updated": {
"type" : "date"
},
"hasExtendedWorking": {
"type" : "boolean"
}
},
"relations": {
"disabilityGrade": {

View File

@ -17,6 +17,9 @@
"ZoneClosure": {
"dataSource": "vn"
},
"ZoneConfig": {
"dataSource": "vn"
},
"ZoneEvent": {
"dataSource": "vn"
},

View File

@ -0,0 +1,28 @@
{
"name": "ZoneConfig",
"options": {
"mysql": {
"table": "zoneConfig"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"scope": {
"type": "number"
},
"forwardDays": {
"type": "number"
}
},
"relations": {
"address": {
"type": "belongsTo",
"model": "Address",
"foreignKey": "defaultAddressFk"
}
}
}

View File

@ -14,4 +14,18 @@ module.exports = Self => {
Self.validatesPresenceOf('agencyModeFk', {
message: `Agency cannot be blank`
});
Self.validatesPresenceOf('price', {
message: 'Price cannot be blank'
});
Self.validateAsync('price', priceIsValid, {
message: 'Price must be greater than 0'
});
async function priceIsValid(err, done) {
if (this.price <= 0)
err();
done();
}
};

View File

@ -1,9 +1,9 @@
{
"name": "Zone",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "zone"
@ -48,30 +48,35 @@
}
},
"relations": {
"agencyMode": {
"type": "belongsTo",
"model": "AgencyMode",
"foreignKey": "agencyModeFk"
"agencyMode": {
"type": "belongsTo",
"model": "AgencyMode",
"foreignKey": "agencyModeFk"
},
"events": {
"type": "hasMany",
"model": "ZoneEvent",
"foreignKey": "zoneFk"
},
"type": "hasMany",
"model": "ZoneEvent",
"foreignKey": "zoneFk"
},
"exclusions": {
"type": "hasMany",
"model": "ZoneExclusion",
"type": "hasMany",
"model": "ZoneExclusion",
"foreignKey": "zoneFk"
},
"warehouses": {
"type": "hasMany",
"model": "ZoneWarehouse",
"foreignKey": "zoneFk"
},
},
"closures": {
"type": "hasMany",
"model": "ZoneClosure",
"foreignKey": "zoneFk"
}
}
},
"address": {
"type": "belongsTo",
"model": "Address",
"foreignKey": "addressFk"
}
}
}

View File

@ -0,0 +1,6 @@
subject: Incoterms Authorization
title: Incoterms Authorization
description:
dear: Dear customer
instructions: Please find attached the Incoterms authorization form, which you must complete and sign.
conclusion: Thank you for your attention!

View File

@ -0,0 +1,16 @@
reportName: balance-compensation
Place: Algemesí, on
Compensation: Compensation of debtor and creditor balances
In one hand: On one hand
CIF: with CIF
NIF: with NIF
Home: and address located at
In other hand: On the other hand
Sr: Mr./Ms.
Agree: Agree
Date: On the date of
Compensate: the balance of has been compensated
From client: from the client/supplier
Against the balance of: against the balance of
Reception: Please confirm receipt of this compensation at the email
Greetings: Best regards,

View File

@ -0,0 +1,39 @@
reportName: autorization-incoterms
description: '<em>{socialName}</em> a duly constituted and responsible company <em>limited</em>
and registered under corporate law {country} and here represented by {socialName}, with address in {address},
CIF <em>{fiscalID}</em>. Hereinafter referred to as {name}.'
issued: 'In {0}, on {1} of {2} of {3}'
client: 'Customer {0}'
declaration: '<em>{socialName}</em> hereby declares that:'
declarations:
- 'All purchases made by {socialName} with {companyName} They are delivered according to the conditions defined in the Incoterm.'
- '{socialName} recognizes that it is important for {companyName} have
proof of intra-community delivery of the goods to {destinationCountry} to
be able to invoice with 0% VAT.'
- 'Therefore, by signing this agreement, {socialName} declares that all goods
purchased from {companyName} will be delivered to {destinationCountry}.'
- 'Besides, {socialName} shall, at the first request of {companyName},
provide proof that all products purchased from {companyName} have
been delivered in {destinationCountry}.'
- 'In addition to the above, {companyName} will provide to {socialName}
a monthly summary that includes all bills (and corresponding deliveries).
{socialName} will sign and return the monthly summary to {companyName},
S.L. within 5 days of receiving the summary.'
signer:
representative: Representative
representativeRole: Position of the representative
signed: Date of signature
manager: Manager
months:
- 'January'
- 'February'
- 'March'
- 'April'
- 'May'
- 'June'
- 'July'
- 'August'
- 'September'
- 'October'
- 'November'
- 'December'