diff --git a/back/methods/osrm-config/optimize.js b/back/methods/osrm-config/optimize.js
new file mode 100644
index 0000000000..e0412c74cc
--- /dev/null
+++ b/back/methods/osrm-config/optimize.js
@@ -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;
+            }
+        }
+    };
+};
diff --git a/back/methods/osrm-config/specs/optimize.spec.js b/back/methods/osrm-config/specs/optimize.spec.js
new file mode 100644
index 0000000000..9f2adccc60
--- /dev/null
+++ b/back/methods/osrm-config/specs/optimize.spec.js
@@ -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');
+    });
+});
diff --git a/back/methods/vn-user/acls.js b/back/methods/vn-user/acls.js
index 7da75ed2cc..347cfa4269 100644
--- a/back/methods/vn-user/acls.js
+++ b/back/methods/vn-user/acls.js
@@ -19,7 +19,7 @@ module.exports = Self => {
                 if (acl.principalType == 'ROLE' && acl.permission == 'ALLOW') {
                     const staticAcl = {
                         model: model.name,
-                        property: '*',
+                        property: acl.property,
                         accessType: acl.accessType,
                         permission: acl.permission,
                         principalType: acl.principalType,
diff --git a/back/model-config.json b/back/model-config.json
index c1682f29a2..2ced867f7a 100644
--- a/back/model-config.json
+++ b/back/model-config.json
@@ -88,6 +88,9 @@
     "Language": {
         "dataSource": "vn"
     },
+    "OsrmConfig": {
+        "dataSource": "vn"
+    },
     "Machine": {
         "dataSource": "vn"
     },
diff --git a/back/models/osrm-config.js b/back/models/osrm-config.js
new file mode 100644
index 0000000000..f738f305c1
--- /dev/null
+++ b/back/models/osrm-config.js
@@ -0,0 +1,4 @@
+module.exports = Self => {
+    require('../methods/osrm-config/optimize')(Self);
+};
+
diff --git a/back/models/osrm-config.json b/back/models/osrm-config.json
new file mode 100644
index 0000000000..ae712ba05a
--- /dev/null
+++ b/back/models/osrm-config.json
@@ -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
+		}
+	}
+}
diff --git a/db/dump/.dump/data.sql b/db/dump/.dump/data.sql
index f45773735c..cd978e4a8e 100644
--- a/db/dump/.dump/data.sql
+++ b/db/dump/.dump/data.sql
@@ -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);
diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql
index 663705ff51..b890b391c8 100644
--- a/db/dump/fixtures.before.sql
+++ b/db/dump/fixtures.before.sql
@@ -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),
@@ -974,26 +974,30 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
         ('SER', 'Services'),
         ('VT',  'Sales');
 
-INSERT INTO `vn`.`item`(`id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenseFk`,
-    `comment`, `relevancy`, `image`, `subName`, `minPrice`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `weightByPiece`)
-    VALUES
-        (1,  2, 1,    1, NULL,              1,    06021010, 2000000000, NULL, 0, '1',  NULL, 0, 'EMB',   0,  NULL,   'V',  0, 3),
-        (2,  2, 1,    2, NULL,              1,    06021010, 2000000000, NULL, 0, '2',  NULL, 0, 'VT',   0,  NULL,   'H',  0, 2),
-        (3,  1, 1,    3, NULL,              1,    05080000, 4751000000, NULL, 0, '3',  NULL, 0, 'VT',   0,  NULL,   NULL, 0, 5),
-        (4,  1, 1,    1, 'Increases block', 1,    05080000, 4751000000, NULL, 0, '4',  NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (5,  3, 1,    2, NULL,              2,    06021010, 4751000000, NULL, 0, '5',  NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (6,  5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '6',  NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (7,  5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '7',  NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (8,  2, 1,    1, NULL,              1,    06021010, 2000000000, NULL, 0, '8',  NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (9,  2, 1,    2, NULL,              1,    06021010, 2000000000, NULL, 0, '9',  NULL, 0, 'VT',   1,  NULL,   NULL, 0, NULL),
-        (10, 1, 1,    3, NULL,              1,    05080000, 4751000000, NULL, 0, '10', NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (11, 1, 1,    1, NULL,              1,    05080000, 4751000000, NULL, 0, '11', NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (12, 3, 1,    2, NULL,              2,    06021010, 4751000000, NULL, 0, '12', NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL),
-        (13, 5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 'VT',   1,  NULL,   NULL, 1, NULL),
-        (14, 5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'VT',   1,  NULL,   NULL, 0, NULL),
-        (15, 4, NULL, 1, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'EMB',  0,  NULL,   NULL, 0, NULL),
-        (16, 6, NULL, 1, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'EMB',  0,  NULL,   NULL, 0, NULL),
-        (71, 6, NULL, 1, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'VT',   0,  NULL,   NULL, 0, NULL);
+INSERT INTO `vn`.`item`(
+    `id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenseFk`,
+    `comment`, `relevancy`, `image`, `subName`, `minPrice`, `family`, `isFloramondo`, `genericFk`,
+    `itemPackingTypeFk`, `hasMinPrice`, `weightByPiece`, `isCustomInspectionRequired`
+)
+VALUES
+    (1,  2, 1,    1, NULL,              1,    06021010, 2000000000, NULL, 0, '1',  NULL, 0, 'EMB',  0,  NULL,	'V',	0, 3, 		1),
+    (2,  2, 1,    2, NULL,              1,    06021010, 2000000000, NULL, 0, '2',  NULL, 0, 'VT',   0,  NULL,   'H',  	0, 2, 		1),
+    (3,  1, 1,    3, NULL,              1,    05080000, 4751000000, NULL, 0, '3',  NULL, 0, 'VT',   0,  NULL,   NULL, 	0, 5, 		0),
+    (4,  1, 1,    1, 'Increases block', 1,    05080000, 4751000000, NULL, 0, '4',  NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (5,  3, 1,    2, NULL,              2,    06021010, 4751000000, NULL, 0, '5',  NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (6,  5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '6',  NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (7,  5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '7',  NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (8,  2, 1,    1, NULL,              1,    06021010, 2000000000, NULL, 0, '8',  NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (9,  2, 1,    2, NULL,              1,    06021010, 2000000000, NULL, 0, '9',  NULL, 0, 'VT',   1,  NULL,   NULL, 	0, NULL,	0),
+    (10, 1, 1,    3, NULL,              1,    05080000, 4751000000, NULL, 0, '10', NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (11, 1, 1,    1, NULL,              1,    05080000, 4751000000, NULL, 0, '11', NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (12, 3, 1,    2, NULL,              2,    06021010, 4751000000, NULL, 0, '12', NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0),
+    (13, 5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 'VT',   1,  NULL,   NULL, 	1, NULL,	0),
+    (14, 5, 1,    2, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'VT',   1,  NULL,   NULL, 	0, NULL,	0),
+    (15, 4, NULL, 1, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'EMB',  0,  NULL,   NULL, 	0, NULL,	0),
+    (16, 6, NULL, 1, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'EMB',  0,  NULL,   NULL, 	0, NULL,	0),
+    (71, 6, NULL, 1, NULL,              NULL, 06021010, 4751000000, NULL, 0, '',   NULL, 0, 'VT',   0,  NULL,   NULL, 	0, NULL,	0);
+
 
 -- Update the taxClass after insert of the items
 UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2
@@ -1516,21 +1520,24 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
         (8,  DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00,  500,  'eight travel',   1, 2, 10, FALSE, NULL),
         (10, DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY),   DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY),   5, 1, 1, 50.00,  500,  'nineth travel',  1, 2, 10, TRUE, 2),
         (11, util.VN_CURDATE() - INTERVAL 1 DAY          ,                              util.VN_CURDATE(),   6, 3, 0, 50.00, 500, 'eleventh travel',  1, 2, 4, FALSE, NULL),
-        (12, util.VN_CURDATE()                           ,             util.VN_CURDATE() + INTERVAL 1 DAY,   6, 3, 0, 50.00, 500, 'eleventh travel',  1, 2, 4, FALSE, NULL);
+        (12, util.VN_CURDATE()                           ,             util.VN_CURDATE() + INTERVAL 1 DAY,   6, 3, 0, 50.00, 500, 'eleventh travel',  1, 2, 4, FALSE, NULL),
+        (13,  util.VN_CURDATE() - INTERVAL 1 MONTH - INTERVAL 1 DAY, util.VN_CURDATE() - INTERVAL 1 MONTH,   6, 3, 0, 50.00, 500, 'eleventh travel',  1, 2, 4, FALSE, NULL);
 
 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, 'IN2010', 'Movement 10',1,                  '', 'product'),
+        (11,    4,  DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH),  1, 1, 442, 'IN2011', 'Movement 11',0,                  '', 'product'),
+        (12,    4,  util.VN_CURDATE() - INTERVAL 1 MONTH,            13, 1, 442, 'IN2012', 'Movement 12',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 +1577,9 @@ 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),
+        (18, 12, 1, 50,      5000,   4, 1, 1.500, 1.500, 0.000, 1,  1,  'grouping', 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
@@ -1920,7 +1929,7 @@ INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`)
 
 INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`)
     VALUES
-        (1, 1, 1, 21, 1,  1, 2, 5),
+        (1, 1, 1, 21, 7,  1, 2, 5),
         (2, 1, 2, 21, 7,  2, 2, 5),
         (3, 2, 7, 21, 9,  3, 2, 5),
         (4, 3, 7, 21, 15, 8, 2, 5),
@@ -3963,7 +3972,7 @@ VALUES(1, '');
 
 INSERT INTO dipole.expedition_PrintOut (expeditionFk, ticketFk, addressFk, street, postalCode, city, shopName, isPrinted, created, printerFk, routeFk, parkingCode,
 truckName, clientFk, phone, province, agency, m3, workerCode, itemFk, quantity, longName, shelvingFk, comments)
-VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, NULL, 'NCC', NULL);
+VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, 'Ranged Reinforced weapon sniper rifle 700mm' , 'NCC', NULL);
 
 INSERT INTO vn.accountDetail
 (id, value, accountDetailTypeFk, supplierAccountFk)
@@ -4035,3 +4044,15 @@ INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel)
 
 INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate)
 	VALUES (1106,'26493101E','2019-09-20');
+
+INSERT INTO vn.referenceRate (currencyFk, dated, value)
+    VALUES (2, '2000-12-01', 1.0495),
+            (2, '2001-01-01', 1.0531),
+            (2, '2001-02-01', 7.6347);
+
+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;
diff --git a/db/routines/hedera/procedures/order_confirmWithUser.sql b/db/routines/hedera/procedures/order_confirmWithUser.sql
index 644d68a878..db83cba5c3 100644
--- a/db/routines/hedera/procedures/order_confirmWithUser.sql
+++ b/db/routines/hedera/procedures/order_confirmWithUser.sql
@@ -107,7 +107,7 @@ BEGIN
 	) INTO vHas0Amount;
 
 	IF vHas0Amount THEN
-		CALL util.throw('Hay líneas vacías. Por favor, elimínelas');
+		CALL util.throw('orderLinesWithZero');
 	END IF;
 
 	START TRANSACTION;
diff --git a/db/routines/sage/procedures/invoiceIn_add.sql b/db/routines/sage/procedures/invoiceIn_add.sql
index 1d411cfd0d..8fdbb9ce32 100644
--- a/db/routines/sage/procedures/invoiceIn_add.sql
+++ b/db/routines/sage/procedures/invoiceIn_add.sql
@@ -4,10 +4,10 @@ BEGIN
 /**
  * Traslada la info de contabilidad relacionada con las facturas recibidas
  *
- * @vInvoiceInFk Factura recibida
- * @vXDiarioFk Id tabla XDiario
+ * @param vInvoiceInFk Factura recibida
+ * @param vXDiarioFk Id tabla XDiario
  */
-    DECLARE vInvoiceInOriginalFk INT;
+	DECLARE vInvoiceInOriginalFk INT;
 	DECLARE vDone BOOL DEFAULT FALSE;
 	DECLARE vBase DOUBLE;
 	DECLARE vVat DOUBLE;
@@ -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,
@@ -204,32 +204,31 @@ BEGIN
 		FROM vn.invoiceInCorrection
 		WHERE correctingFk = vInvoiceInFk;
 
-	IF vInvoiceInOriginalFk THEN 
-
+	IF vInvoiceInOriginalFk THEN
 		UPDATE movContaIVA mci
-				JOIN vn.invoiceInRefund iir ON iir.invoiceInRefundFk = vInvoiceInFk
+				JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk
+				JOIN vn.siiTypeInvoiceIn st ON st.id = iic.siiTypeInvoiceInFk
 				JOIN (SELECT issued,
-							SUM(sub.taxableBase) taxableBase, 
+							SUM(sub.taxableBase) taxableBase,
 							SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat
 						FROM(SELECT issued,
-									SUM(iit.taxableBase) taxableBase, 
+									SUM(iit.taxableBase) taxableBase,
 									ti.PorcentajeIva
-								FROM vn.invoiceIn i 
+								FROM vn.invoiceIn i
 									JOIN vn.invoiceInTax iit ON iit.invoiceInFk = i.id
-									JOIN sage.TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk
+									JOIN TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk
 								WHERE i.id = vInvoiceInOriginalFk
 								GROUP BY ti.CodigoIva)sub
 					)invoiceInOriginal
 				JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa'
 			SET mci.TipoRectificativa = iir.refundCategoryFk,
-				mci.ClaseAbonoRectificativas = iir.refundType, 
+				mci.ClaseAbonoRectificativas = iir.refundType,
 				mci.FechaFacturaOriginal = invoiceInOriginal.issued,
 				mci.FechaOperacion = invoiceInOriginal.issued,
 				mci.BaseImponibleOriginal = invoiceInOriginal.taxableBase,
 				mci.CuotaIvaOriginal = invoiceInOriginal.vat,
 				mci.ClaveOperacionFactura = co.ClaveOperacionFactura_
 			WHERE mci.id = vXDiarioFk;
-
 	END IF;
 END$$
-DELIMITER ;
\ No newline at end of file
+DELIMITER ;
diff --git a/db/routines/sage/procedures/invoiceOut_add.sql b/db/routines/sage/procedures/invoiceOut_add.sql
index 95d6a56dd5..f9c6f6b87a 100644
--- a/db/routines/sage/procedures/invoiceOut_add.sql
+++ b/db/routines/sage/procedures/invoiceOut_add.sql
@@ -169,6 +169,7 @@ BEGIN
 		UPDATE movContaIVA mci
 				JOIN vn.invoiceOut i ON i.id = vInvoiceOutCorrectedFk
 				JOIN vn.invoiceCorrection ic ON ic.correctedFk = vInvoiceOutCorrectedFk
+				JOIN vn.siiTypeInvoiceOut st ON st.id = ic.siiTypeInvoiceOutFk
 				JOIN (SELECT SUM(IF(IFNULL(e.vatFk, TRUE), iot.taxableBase, 0)) taxableBase, 
 							 SUM(IF(IFNULL(e.vatFk, TRUE), iot.vat, 0)) vat,
 							 SUM(IF(IFNULL(e.vatFk, TRUE), 0, iot.vat)) equ
@@ -177,8 +178,8 @@ BEGIN
 						WHERE iot.invoiceOutFk = vInvoiceOutCorrectedFk
 					) tax
 				JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa'
-			SET mci.TipoRectificativa = 2,
-				mci.ClaseAbonoRectificativas = 1, 
+			SET mci.TipoRectificativa = ic.cplusRectificationTypeFk,
+				mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''), 
 				mci.FechaFacturaOriginal = i.issued,
 				mci.FechaOperacion = i.issued,
 				mci.BaseImponibleOriginal = tax.taxableBase,
diff --git a/db/routines/vn/functions/entry_getCommission.sql b/db/routines/vn/functions/entry_getCommission.sql
index a4afdabd48..f8c1ce3b4e 100644
--- a/db/routines/vn/functions/entry_getCommission.sql
+++ b/db/routines/vn/functions/entry_getCommission.sql
@@ -11,6 +11,7 @@ BEGIN
 	DECLARE vCurrentCommission INT;
 	DECLARE vIsNotEUR INT;
 	DECLARE vLastEntryFk INT;
+	DECLARE vLanded INT;
 
 	SELECT count(*) INTO vIsNotEUR
 			FROM currency c
@@ -26,23 +27,25 @@ BEGIN
 
 		RETURN IFNULL(vCommission, 0);
 	ELSE
+		SELECT landed INTO vLanded
+			FROM travel
+			WHERE id = vTravelFk;
+
 		SELECT e.id INTO vLastEntryFk
 			FROM `entry` e
 				JOIN travel tr ON tr.id = e.travelFk
-				WHERE e.supplierFk = vSupplierFk
-				ORDER BY tr.landed DESC
-				LIMIT 1;
+			WHERE e.supplierFk = vSupplierFk
+			ORDER BY (vLanded <= tr.landed), tr.landed DESC
+			LIMIT 1;
 
 		IF vLastEntryFk THEN
 			SELECT commission INTO vCurrentCommission
 				FROM `entry`
 				WHERE id = vLastEntryFk;
-
 		ELSE
 			SELECT commission INTO vCurrentCommission
 				FROM supplier s
 				WHERE s.id = vSupplierFk;
-
 		END IF;
 
 		RETURN vCurrentCommission;
diff --git a/db/routines/vn/procedures/claimRatio_add.sql b/db/routines/vn/procedures/claimRatio_add.sql
index 8c32136440..5e2e66a8ec 100644
--- a/db/routines/vn/procedures/claimRatio_add.sql
+++ b/db/routines/vn/procedures/claimRatio_add.sql
@@ -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
diff --git a/db/routines/vn/procedures/inventoryFailureAdd.sql b/db/routines/vn/procedures/inventoryFailureAdd.sql
deleted file mode 100644
index e2b5fa4a0e..0000000000
--- a/db/routines/vn/procedures/inventoryFailureAdd.sql
+++ /dev/null
@@ -1,48 +0,0 @@
-DELIMITER $$
-CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`inventoryFailureAdd`()
-BEGIN
-
-DECLARE done BOOL DEFAULT FALSE;
-DECLARE vTicketFk INT;
-
-DECLARE rs CURSOR FOR
-		SELECT id FROM vn.ticket 
-			WHERE shipped = util.yesterday() 
-				AND clientFk = 400
-                AND warehouseFk IN (1,44);
-
-DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
-OPEN rs;
-
-FETCH rs INTO vTicketFk;
-
-WHILE NOT done DO
-   
-    INSERT INTO vn.inventoryFailure(dated, itemFk, quantity, value, warehouseFk, throwerFk)
-		SELECT 	t.shipped, 
-				s.itemFk, 
-				s.quantity, 
-				b.buyingValue + b.freightValue + b.packageValue + b.comissionValue,
-				t.warehouseFk, 
-				w.id
-			FROM vn.ticket t
-				JOIN vn.sale s ON s.ticketFk = t.id
-				LEFT JOIN cache.last_buy lb ON lb.warehouse_id = t.warehouseFk AND item_id = s.itemFk
-				LEFT JOIN vn.buy b ON b.id = lb.buy_id
-				LEFT JOIN vn.worker w ON w.code = LEFT(s.concept, 3)
-		WHERE t.id = vTicketFk
-			AND s.quantity > 0;
-
-	FETCH rs INTO vTicketFk;
-    
-END WHILE;
-
-
-CLOSE rs;
-
-
-
-
-END$$
-DELIMITER ;
diff --git a/db/routines/vn/procedures/invoiceIn_booking.sql b/db/routines/vn/procedures/invoiceIn_booking.sql
index cfe3adb0b6..ef68e48045 100644
--- a/db/routines/vn/procedures/invoiceIn_booking.sql
+++ b/db/routines/vn/procedures/invoiceIn_booking.sql
@@ -43,7 +43,7 @@ BEGIN
 				ii.cplusTaxBreakFk,
 				ii.cplusSubjectOpFk,
 				ii.siiTypeInvoiceInFk,
-				ii.cplusRectificationTypeFk,
+				ic.cplusRectificationTypeFk,
 				ii.booked,
 				IFNULL(a.isUeeMember, c.isUeeMember) isUeeMember,
 				(c.id = cc.id) isSameCountry,
@@ -66,6 +66,7 @@ BEGIN
 				e.name expenseName
 			FROM invoiceIn ii
 				JOIN supplier s ON s.id = ii.supplierFk
+				LEFT JOIN invoiceInCorrection ic ON ic.correctingFk = ii.id	
 				LEFT JOIN province p ON p.id = s.provinceFk
 				LEFT JOIN autonomy a ON a.id = p.autonomyFk
 				JOIN country c ON c.id = s.countryFk
diff --git a/db/routines/vn/procedures/item_cleanFloramondo.sql b/db/routines/vn/procedures/item_cleanFloramondo.sql
index 849cfe93d2..21d8ebe3c0 100644
--- a/db/routines/vn/procedures/item_cleanFloramondo.sql
+++ b/db/routines/vn/procedures/item_cleanFloramondo.sql
@@ -164,10 +164,6 @@ BEGIN
 			SET itemFk = vItemNew
 			WHERE itemFk = vItemOld;
 
-		UPDATE inventoryFailure
-			SET itemFk = vItemNew
-			WHERE itemFk = vItemOld;
-
 		UPDATE genericAllocation
 			SET itemFk = vItemNew
 			WHERE itemFk = vItemOld;
diff --git a/db/routines/vn/procedures/ticket_canAdvance.sql b/db/routines/vn/procedures/ticket_canAdvance.sql
index e8fc70bba0..cee706e08c 100644
--- a/db/routines/vn/procedures/ticket_canAdvance.sql
+++ b/db/routines/vn/procedures/ticket_canAdvance.sql
@@ -52,7 +52,8 @@ BEGIN
 				IFNULL(dest.nickname, origin.nickname) nickname,
 				dest.landed,
 				dest.preparation,
-				origin.departmentFk
+				origin.departmentFk,
+				origin.saleClonedFk
 			FROM (
 				SELECT s.ticketFk,
 						c.salesPersonFk workerFk,
@@ -73,11 +74,13 @@ BEGIN
 						t.warehouseFk,
 						t.companyFk,
 						t.agencyModeFk,
-						wd.departmentFk
+						wd.departmentFk,
+						sc.saleClonedFk
 					FROM ticket t
 						JOIN client c ON c.id = t.clientFk
 						JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk
 						JOIN sale s ON s.ticketFk = t.id
+						LEFT JOIN saleCloned sc ON sc.saleClonedFk = s.id
 						JOIN saleVolume sv ON sv.saleFk = s.id
 						JOIN item i ON i.id = s.itemFk
 						JOIN ticketState ts ON ts.ticketFk = t.id
diff --git a/db/routines/vn/procedures/travel_checkRaid.sql b/db/routines/vn/procedures/travel_checkRaid.sql
index 64f3355e2d..885fc718a6 100644
--- a/db/routines/vn/procedures/travel_checkRaid.sql
+++ b/db/routines/vn/procedures/travel_checkRaid.sql
@@ -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 ;
diff --git a/db/routines/vn/procedures/travel_moveRaids.sql b/db/routines/vn/procedures/travel_moveRaids.sql
index cf0fce23c3..17d7ecc4c5 100644
--- a/db/routines/vn/procedures/travel_moveRaids.sql
+++ b/db/routines/vn/procedures/travel_moveRaids.sql
@@ -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$$
diff --git a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql
index 95b1d98a97..8c2785e38a 100644
--- a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql
+++ b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql
@@ -3,24 +3,30 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_afterUpdate`
 	AFTER UPDATE ON `invoiceIn`
 	FOR EACH ROW
 BEGIN
-	IF NEW.issued != OLD.issued    
-		OR NEW.currencyFk != OLD.currencyFk THEN
+	DECLARE vIsEuro BOOL;
+	
+	SELECT `code` = 'EUR' INTO vIsEuro 
+		FROM currency 
+		WHERE id = NEW.currencyFk;
+
+	IF (NOT NEW.issued <=> OLD.issued    
+		OR NEW.currencyFk <> OLD.currencyFk) THEN
 
 		UPDATE invoiceInTax iit
 				JOIN invoiceIn ii ON ii.id = iit.invoiceInFk
 				LEFT JOIN referenceRate rr ON rr.dated = ii.issued
 					AND rr.currencyFk = ii.currencyFk 
-			SET iit.taxableBase = IF(iit.foreignValue IS NULL, iit.taxableBase, iit.foreignValue / rr.value)
+			SET iit.taxableBase = IF(vIsEuro, iit.taxableBase, iit.foreignValue / rr.value),
+				iit.foreignValue = IF(vIsEuro, NULL, iit.foreignValue)
 			WHERE ii.id = NEW.id;
 		
 		UPDATE invoiceInDueDay iidd
 				JOIN invoiceIn ii ON ii.id = iidd.invoiceInFk
 				LEFT JOIN referenceRate rr ON rr.dated = ii.issued
 					AND rr.currencyFk = ii.currencyFk 
-			SET iidd.amount = IF(iidd.foreignValue IS NULL, iidd.amount, iidd.foreignValue / rr.value)
+			SET iidd.amount = IF(vIsEuro, iidd.amount, iidd.foreignValue / rr.value),
+				iidd.foreignValue = IF(vIsEuro, NULL, iidd.foreignValue)
 			WHERE ii.id = NEW.id;    
-        
     END IF;
-
 END$$
 DELIMITER ;
diff --git a/db/routines/vn/triggers/route_afterUpdate.sql b/db/routines/vn/triggers/route_afterUpdate.sql
index 447608acc9..a15c1a4b76 100644
--- a/db/routines/vn/triggers/route_afterUpdate.sql
+++ b/db/routines/vn/triggers/route_afterUpdate.sql
@@ -22,6 +22,7 @@ BEGIN
 		OR !(NEW.workerFk <=> OLD.workerFk)
 		OR !(NEW.m3 <=> OLD.m3)
 		OR !(NEW.agencyModeFk <=> OLD.agencyModeFk)
+        OR !(NEW.dated <=> OLD.dated)
 		OR !(NEW.vehicleFk <=> OLD.vehicleFk)THEN
 			CALL route_calcCommission(NEW.id);
 	END IF;
diff --git a/db/routines/vn/triggers/travel_beforeUpdate.sql b/db/routines/vn/triggers/travel_beforeUpdate.sql
index 256dd35f87..5a27b43b42 100644
--- a/db/routines/vn/triggers/travel_beforeUpdate.sql
+++ b/db/routines/vn/triggers/travel_beforeUpdate.sql
@@ -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
diff --git a/db/versions/11320-salmonRose/00-firstScript.sql b/db/versions/11320-salmonRose/00-firstScript.sql
new file mode 100644
index 0000000000..cd3431fee7
--- /dev/null
+++ b/db/versions/11320-salmonRose/00-firstScript.sql
@@ -0,0 +1,11 @@
+INSERT INTO hedera.message (code, description)
+	VALUES ('orderLinesWithZero','There are empty lines. Please delete them');
+
+INSERT INTO hedera.messageI18n (code, lang, description)
+	VALUES ('orderLinesWithZero','es','Hay líneas vacías. Por favor, elimínelas');
+
+INSERT INTO hedera.messageI18n (code, lang, description)
+	VALUES ('orderLinesWithZero','fr','Il y a des lignes vides. Veuillez les supprimer');
+
+INSERT INTO hedera.messageI18n (code, lang, description)
+	VALUES ('orderLinesWithZero','pt','Existem linhas vazias. Por favor, apague-os');
\ No newline at end of file
diff --git a/db/versions/11327-maroonOak/00-firstScript.sql b/db/versions/11327-maroonOak/00-firstScript.sql
new file mode 100644
index 0000000000..a51ee3fff8
--- /dev/null
+++ b/db/versions/11327-maroonOak/00-firstScript.sql
@@ -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` VARCHAR(4) NOT NULL CHECK (`pin` REGEXP '^[0-9]+$'),
+	`puk` VARCHAR(15) NOT NULL CHECK (`pin` REGEXP '^[0-9]+$'),
+	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;
diff --git a/db/versions/11352-blackErica/00-firstScript.sql b/db/versions/11352-blackErica/00-firstScript.sql
new file mode 100644
index 0000000000..659f501614
--- /dev/null
+++ b/db/versions/11352-blackErica/00-firstScript.sql
@@ -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');
\ No newline at end of file
diff --git a/db/versions/11368-whiteAspidistra/00-firstScript.sql b/db/versions/11368-whiteAspidistra/00-firstScript.sql
new file mode 100644
index 0000000000..f36832805f
--- /dev/null
+++ b/db/versions/11368-whiteAspidistra/00-firstScript.sql
@@ -0,0 +1,48 @@
+	USE vn;
+
+	DROP TRIGGER IF EXISTS invoiceIn_beforeUpdate;
+
+	UPDATE invoiceIn 
+		SET cplusRectificationTypeFk = NULL 
+		WHERE cplusRectificationTypeFk = 1;
+
+	DELETE IGNORE FROM cplusRectificationType WHERE id = 1;
+
+	UPDATE cplusRectificationType 
+		SET id = 1 
+		WHERE id = 3;
+
+DELIMITER $$
+CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_beforeUpdate`
+	BEFORE UPDATE ON `invoiceIn`
+	FOR EACH ROW
+BEGIN
+	DECLARE vWithholdingSageFk INT;
+
+	IF NOT (NEW.supplierRef <=> OLD.supplierRef) AND NOT util.checkPrintableChars(NEW.supplierRef) THEN
+		CALL util.throw('The invoiceIn reference contains invalid characters');
+	END IF;
+
+	SET NEW.editorFk = account.myUser_getId();
+
+	IF (SELECT COUNT(*) FROM invoiceIn 
+			WHERE supplierRef = NEW.supplierRef 
+				AND supplierFk = NEW.supplierFk 
+				AND YEAR(issued) = YEAR(NEW.issued)
+				AND id <> NEW.id
+	) THEN
+		CALL util.throw('reference duplicated');
+	END IF;
+
+	IF 	NEW.supplierFk != OLD.supplierFk THEN
+		CALL supplier_checkIsActive(NEW.supplierFk);
+		SELECT withholdingSageFk INTO vWithholdingSageFk
+				FROM supplier 
+				WHERE id = NEW.supplierFk;
+		SET NEW.withholdingSageFk = vWithholdingSageFk;
+	END IF;
+
+END$$
+DELIMITER ;
+
+
diff --git a/db/versions/11368-whiteAspidistra/01-acls.sql b/db/versions/11368-whiteAspidistra/01-acls.sql
new file mode 100644
index 0000000000..6ac98db435
--- /dev/null
+++ b/db/versions/11368-whiteAspidistra/01-acls.sql
@@ -0,0 +1,23 @@
+INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) 
+	VALUES('SiiTypeInvoiceIn', 'find', 'READ', 'ALLOW', 'ROLE', 'salesPerson');
+
+DROP TABLE IF EXISTS vn.invoiceInCorrection;
+
+CREATE TABLE `invoiceInCorrection` (
+	`correctingFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificativa',
+	`correctedFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificada',
+	`cplusRectificationTypeFk` int(10) unsigned NOT NULL,
+	`siiTypeInvoiceInFk` int(10) unsigned NOT NULL,
+	`invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3,
+	PRIMARY KEY (`correctingFk`),
+	KEY `invoiceInCorrection_correctedFk` (`correctedFk`),
+	KEY `invoiceInCorrection_cplusRectificationTypeFk` (`cplusRectificationTypeFk`),
+	KEY `invoiceInCorrection_siiTypeInvoiceIn` (`siiTypeInvoiceInFk`),
+	KEY `invoiceInCorrection_invoiceCorrectionTypeFk` (`invoiceCorrectionTypeFk`),
+	CONSTRAINT `invoiceInCorrection_correctedFk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+	CONSTRAINT `invoiceInCorrection_correctingFk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+	CONSTRAINT `invoiceInCorrection_cplusRectificationTypeFk` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE,
+	CONSTRAINT `invoiceInCorrection_invoiceCorrectionTypeFk` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE,
+	CONSTRAINT `invoiceInCorrection_siiTypeInvoiceIn` FOREIGN KEY (`siiTypeInvoiceInFk`) REFERENCES `siiTypeInvoiceIn` (`id`) ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
+
diff --git a/db/versions/11376-pinkBamboo/00-firstScript.sql b/db/versions/11376-pinkBamboo/00-firstScript.sql
new file mode 100644
index 0000000000..0c1e71a2f0
--- /dev/null
+++ b/db/versions/11376-pinkBamboo/00-firstScript.sql
@@ -0,0 +1,2 @@
+ALTER TABLE vn.`zone` MODIFY COLUMN `price` DECIMAL(10,2);
+
diff --git a/db/versions/11379-yellowCordyline/00-firstScript.sql b/db/versions/11379-yellowCordyline/00-firstScript.sql
new file mode 100644
index 0000000000..8d90ee90c6
--- /dev/null
+++ b/db/versions/11379-yellowCordyline/00-firstScript.sql
@@ -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;
diff --git a/db/versions/11379-yellowCordyline/01-secScript.sql b/db/versions/11379-yellowCordyline/01-secScript.sql
new file mode 100644
index 0000000000..30479229e4
--- /dev/null
+++ b/db/versions/11379-yellowCordyline/01-secScript.sql
@@ -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);
diff --git a/db/versions/11384-grayAnthurium/00-firstScript.sql b/db/versions/11384-grayAnthurium/00-firstScript.sql
new file mode 100644
index 0000000000..b3a7f3da21
--- /dev/null
+++ b/db/versions/11384-grayAnthurium/00-firstScript.sql
@@ -0,0 +1,3 @@
+ALTER TABLE vn.mistakeType
+    ADD `time` int(10) NULL COMMENT 'Segundos que se suelen tardar en arreglar el fallo',
+    ADD code varchar(50) DEFAULT NULL NULL AFTER id;
diff --git a/db/versions/11385-yellowOrchid/00-firstScript.sql b/db/versions/11385-yellowOrchid/00-firstScript.sql
new file mode 100644
index 0000000000..287e9fcab2
--- /dev/null
+++ b/db/versions/11385-yellowOrchid/00-firstScript.sql
@@ -0,0 +1,5 @@
+RENAME TABLE vn.inventoryFailure TO vn.inventoryFailure__;
+ALTER TABLE vn.inventoryFailure__ COMMENT='@deprecated 2024-12-16';
+
+RENAME TABLE vn.inventoryFailureCause TO vn.inventoryFailureCause__;
+ALTER TABLE vn.inventoryFailureCause__ COMMENT='@deprecated 2024-12-16';
diff --git a/db/versions/11390-goldenPalmetto/00-firstScript.sql b/db/versions/11390-goldenPalmetto/00-firstScript.sql
new file mode 100644
index 0000000000..adcc76e4f3
--- /dev/null
+++ b/db/versions/11390-goldenPalmetto/00-firstScript.sql
@@ -0,0 +1,3 @@
+
+ALTER TABLE vn.country
+	ADD CONSTRAINT country_unique_name UNIQUE KEY (name);
diff --git a/db/versions/11391-redPalmetto/00-itemAlter.sql b/db/versions/11391-redPalmetto/00-itemAlter.sql
new file mode 100644
index 0000000000..fc47d5fc05
--- /dev/null
+++ b/db/versions/11391-redPalmetto/00-itemAlter.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `vn`.`item`
+ADD COLUMN `isCustomInspectionRequired` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Indicates if the item requires physical inspection at customs';
diff --git a/loopback/locale/en.json b/loopback/locale/en.json
index 7372ac9a66..80da13ae59 100644
--- a/loopback/locale/en.json
+++ b/loopback/locale/en.json
@@ -246,6 +246,9 @@
 	"ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}",
 	"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"
-}
+	"Sales already moved": "Sales already moved",
+	"Holidays to past days not available": "Holidays to past days not available",
+	"Price cannot be blank": "Price cannot be blank",
+	"There are tickets to be invoiced": "There are tickets to be invoiced",
+	"The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent"
+}
\ No newline at end of file
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 0dc8e53a8d..fcee0e1119 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -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",
+	"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",
+    "There are tickets to be invoiced": "La zona tiene tickets por facturar"
 }
-
diff --git a/modules/account/back/methods/account/sync.js b/modules/account/back/methods/account/sync.js
index 1026c50208..b38e4dd373 100644
--- a/modules/account/back/methods/account/sync.js
+++ b/modules/account/back/methods/account/sync.js
@@ -29,14 +29,14 @@ module.exports = Self => {
         const models = Self.app.models;
         const myOptions = {};
         let tx;
-        
+
         if (typeof options == 'object')
             Object.assign(myOptions, options);
 
         if (!myOptions.transaction) {
             tx = await Self.beginTransaction({});
             myOptions.transaction = tx;
-        };
+        }
 
         try {
             const user = await models.VnUser.findOne({
diff --git a/modules/claim/back/methods/claim/filter.js b/modules/claim/back/methods/claim/filter.js
index f60b6572ed..bacdd40216 100644
--- a/modules/claim/back/methods/claim/filter.js
+++ b/modules/claim/back/methods/claim/filter.js
@@ -80,6 +80,12 @@ module.exports = Self => {
                 description: 'The claimResponsible id',
                 http: {source: 'query'}
             },
+            {
+                arg: 'zoneFk',
+                type: 'string',
+                description: 'The zone name',
+                http: {source: 'query'}
+            },
             {
                 arg: 'myTeam',
                 type: 'boolean',
@@ -174,6 +180,8 @@ module.exports = Self => {
                 to.setHours(23, 59, 59, 999);
 
                 return {'cl.created': {between: [value, to]}};
+            case 'zoneFk':
+                return {'t.zoneFk': value};
             case 'myTeam':
                 if (value)
                     return {'cl.workerFk': {inq: teamMembersId}};
@@ -195,11 +203,15 @@ module.exports = Self => {
                     u.name AS workerName,
                     cs.code stateCode,
                     cs.description stateDescription,
-                    cl.created
+                    cl.created,
+                    z.name zoneName,
+                    z.id zoneId
                 FROM claim cl
                     LEFT JOIN client c ON c.id = cl.clientFk
                     LEFT JOIN account.user u ON u.id = cl.workerFk
-                    LEFT JOIN claimState cs ON cs.id = cl.claimStateFk`
+                    LEFT JOIN claimState cs ON cs.id = cl.claimStateFk
+                    LEFT JOIN ticket t ON t.id = cl.ticketFk
+                    LEFT JOIN zone z ON z.id = t.zoneFk`
         );
 
         stmt.merge(conn.makeSuffix(filter));
diff --git a/modules/client/back/methods/client/canBeInvoiced.js b/modules/client/back/methods/client/canBeInvoiced.js
index cdb8655005..536606b0bd 100644
--- a/modules/client/back/methods/client/canBeInvoiced.js
+++ b/modules/client/back/methods/client/canBeInvoiced.js
@@ -2,7 +2,7 @@ const UserError = require('vn-loopback/util/user-error');
 
 module.exports = function(Self) {
     Self.remoteMethod('canBeInvoiced', {
-        description: 'Change property isEqualizated in all client addresses',
+        description: 'Check if a client can be invoiced',
         accessType: 'READ',
         accepts: [
             {
@@ -38,7 +38,7 @@ module.exports = function(Self) {
             Object.assign(myOptions, options);
 
         const client = await models.Client.findById(id, {
-            fields: ['id', 'isTaxDataChecked', 'hasToInvoice', 'payMethodFk'],
+            fields: ['id', 'isTaxDataChecked', 'hasToInvoice', 'payMethodFk', 'isActive'],
             include:
                 {
                     relation: 'payMethod',
@@ -53,9 +53,6 @@ module.exports = function(Self) {
         if (client.payMethod().code === 'wireTransfer' && !company.supplierAccountFk)
             throw new UserError('The company has not informed the supplier account for bank transfers');
 
-        if (client.isTaxDataChecked && client.hasToInvoice)
-            return true;
-
-        return false;
+        return client.isTaxDataChecked && client.hasToInvoice && client.isActive;
     };
 };
diff --git a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js
index 397be3c921..4012b74093 100644
--- a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js
+++ b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js
@@ -8,6 +8,8 @@ describe('client canBeInvoiced()', () => {
     const activeCtx = {
         accessToken: {userId: userId}
     };
+    let tx;
+    let options;
 
     beforeAll(async() => {
         spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
@@ -15,60 +17,45 @@ describe('client canBeInvoiced()', () => {
         });
     });
 
+    beforeEach(async() => {
+        tx = await models.Client.beginTransaction({});
+        options = {transaction: tx};
+    });
+
+    afterEach(async() => {
+        await tx.rollback();
+    });
+
     it('should return falsy for a client without the data checked', async() => {
-        const tx = await models.Client.beginTransaction({});
+        const client = await models.Client.findById(clientId, null, options);
+        await client.updateAttribute('isTaxDataChecked', false, options);
 
-        try {
-            const options = {transaction: tx};
+        const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options);
 
-            const client = await models.Client.findById(clientId, null, options);
-            await client.updateAttribute('isTaxDataChecked', false, options);
+        expect(canBeInvoiced).toEqual(false);
+    });
 
-            const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options);
+    it('should return falsy for a client not active', async() => {
+        const client = await models.Client.findById(clientId, null, options);
+        await client.updateAttribute('isActive', false, options);
 
-            expect(canBeInvoiced).toEqual(false);
+        const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options);
 
-            await tx.rollback();
-        } catch (e) {
-            await tx.rollback();
-            throw e;
-        }
+        expect(canBeInvoiced).toEqual(false);
     });
 
     it('should return falsy for a client with invoicing disabled', async() => {
-        const tx = await models.Client.beginTransaction({});
+        const client = await models.Client.findById(clientId, null, options);
+        await client.updateAttribute('hasToInvoice', false, options);
 
-        try {
-            const options = {transaction: tx};
+        const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options);
 
-            const client = await models.Client.findById(clientId, null, options);
-            await client.updateAttribute('hasToInvoice', false, options);
-
-            const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options);
-
-            expect(canBeInvoiced).toEqual(false);
-
-            await tx.rollback();
-        } catch (e) {
-            await tx.rollback();
-            throw e;
-        }
+        expect(canBeInvoiced).toEqual(false);
     });
 
     it('should return truthy for an invoiceable client', async() => {
-        const tx = await models.Client.beginTransaction({});
+        const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options);
 
-        try {
-            const options = {transaction: tx};
-
-            const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options);
-
-            expect(canBeInvoiced).toEqual(true);
-
-            await tx.rollback();
-        } catch (e) {
-            await tx.rollback();
-            throw e;
-        }
+        expect(canBeInvoiced).toEqual(true);
     });
 });
diff --git a/modules/client/back/methods/client/updateAddress.js b/modules/client/back/methods/client/updateAddress.js
index 7342b28f18..efef83d6b3 100644
--- a/modules/client/back/methods/client/updateAddress.js
+++ b/modules/client/back/methods/client/updateAddress.js
@@ -72,6 +72,14 @@ module.exports = function(Self) {
             {
                 arg: 'isLogifloraAllowed',
                 type: 'boolean'
+            },
+            {
+                arg: 'longitude',
+                type: 'any',
+            },
+            {
+                arg: 'latitude',
+                type: 'any',
             }
         ],
         returns: {
diff --git a/modules/entry/back/methods/entry/specs/filter.spec.js b/modules/entry/back/methods/entry/specs/filter.spec.js
index 4bf5127b0f..b139b00b6b 100644
--- a/modules/entry/back/methods/entry/specs/filter.spec.js
+++ b/modules/entry/back/methods/entry/specs/filter.spec.js
@@ -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) {
diff --git a/modules/entry/back/model-config.json b/modules/entry/back/model-config.json
index 5c45b6e07d..49c2df2db8 100644
--- a/modules/entry/back/model-config.json
+++ b/modules/entry/back/model-config.json
@@ -28,5 +28,8 @@
     },
     "StockBought": {
         "dataSource": "vn"
+    },
+    "InventoryConfig": {
+        "dataSource": "vn"
     }
 }
diff --git a/modules/entry/back/models/inventory-config.json b/modules/entry/back/models/inventory-config.json
new file mode 100644
index 0000000000..caa39db888
--- /dev/null
+++ b/modules/entry/back/models/inventory-config.json
@@ -0,0 +1,18 @@
+{
+    "name": "InventoryConfig",
+    "base": "VnModel",
+    "options": {
+        "mysql": {
+        "table": "inventoryConfig"
+        }
+    },
+    "properties": {
+        "id": {
+            "type": "number",
+            "id": true
+        },
+        "supplierFk": {
+            "type": "number"
+        }
+    }
+}
diff --git a/modules/invoiceIn/back/locale/invoiceIn/en.yml b/modules/invoiceIn/back/locale/invoiceIn/en.yml
index 9e94eba0d4..f590f9656f 100644
--- a/modules/invoiceIn/back/locale/invoiceIn/en.yml
+++ b/modules/invoiceIn/back/locale/invoiceIn/en.yml
@@ -17,4 +17,6 @@ columns:
   isVatDeductible: is VAT deductible
   withholdingSageFk: withholding
   expenseFkDeductible: expense deductible
-  editorFk: editor
\ No newline at end of file
+  editorFk: editor
+  siiTrasCendencyInvoiceInFk: SII tax regime
+  siiTypeInvoiceInFk: SII Type
\ No newline at end of file
diff --git a/modules/invoiceIn/back/locale/invoiceIn/es.yml b/modules/invoiceIn/back/locale/invoiceIn/es.yml
index bd64c4327a..64ded6acaa 100644
--- a/modules/invoiceIn/back/locale/invoiceIn/es.yml
+++ b/modules/invoiceIn/back/locale/invoiceIn/es.yml
@@ -5,7 +5,7 @@ columns:
   serial: serie
   supplierFk: proveedor
   issued: fecha emisión
-  supplierRef: referéncia proveedor
+  supplierRef: referencia proveedor
   isBooked: facturado
   currencyFk: moneda
   created: creado
@@ -17,4 +17,6 @@ columns:
   isVatDeductible: impuesto deducible
   withholdingSageFk: código de retención
   expenseFkDeductible: gasto deducible
-  editorFk: editor
\ No newline at end of file
+  editorFk: editor
+  siiTrasCendencyInvoiceInFk: régimen fiscal SII
+  siiTypeInvoiceInFk: tipo SII
\ No newline at end of file
diff --git a/modules/invoiceIn/back/methods/invoice-in/corrective.js b/modules/invoiceIn/back/methods/invoice-in/corrective.js
index 05f632bcd5..e7088d2010 100644
--- a/modules/invoiceIn/back/methods/invoice-in/corrective.js
+++ b/modules/invoiceIn/back/methods/invoice-in/corrective.js
@@ -44,7 +44,7 @@ module.exports = Self => {
                 correctingFk: clone.id,
                 correctedFk: id,
                 cplusRectificationTypeFk: invoiceType,
-                siiTypeInvoiceOutFk: invoiceClass,
+                siiTypeInvoiceInFk: invoiceClass,
                 invoiceCorrectionTypeFk: invoiceReason
             }, myOptions);
 
diff --git a/modules/invoiceIn/back/methods/invoice-in/filter.js b/modules/invoiceIn/back/methods/invoice-in/filter.js
index 936f7bb6c2..f081368e46 100644
--- a/modules/invoiceIn/back/methods/invoice-in/filter.js
+++ b/modules/invoiceIn/back/methods/invoice-in/filter.js
@@ -91,6 +91,10 @@ module.exports = Self => {
             {
                 arg: 'supplierActivityFk',
                 type: 'string',
+            },
+            {
+                arg: 'companyFk',
+                type: 'number',
             }
         ],
         returns: {
@@ -161,8 +165,8 @@ module.exports = Self => {
                     : {'ii.id': {nin: correcteds.map(x => x.correctingFk)}};
             case 'correctedFk':
                 return {'ii.id': {inq: correctings.map(x => x.correctingFk)}};
-            case 'supplierActivityFk':
-                return {'s.supplierActivityFk': value};
+            case 'companyFk':
+                return {'ii.companyFk': value};
             }
         });
 
@@ -184,7 +188,9 @@ module.exports = Self => {
                 s.name supplierName,
                 s.account,
                 SUM(iid.amount) amount,
-                sub.code awbCode
+                sub.code awbCode,
+                c.code,
+                MIN(iid.dueDated) dueDated
             FROM invoiceIn ii
                 JOIN supplier s ON s.id = ii.supplierFk
                 LEFT JOIN invoiceInDueDay iid ON iid.invoiceInFk = ii.id
@@ -199,7 +205,8 @@ module.exports = Self => {
                     GROUP BY de.duaFk
                 ) sub ON sub.duaFk = d.id
                 LEFT JOIN company co ON co.id = ii.companyFk
-                LEFT JOIN dms dm ON dm.id = ii.docFk`
+                LEFT JOIN dms dm ON dm.id = ii.docFk
+                JOIN company c ON c.id = ii.companyFk`,
         );
 
         const sqlWhere = conn.makeWhere(filter.where);
diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js
index c63f024397..aee8d3f2c3 100644
--- a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js
+++ b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js
@@ -15,11 +15,11 @@ describe('invoiceIn corrective()', () => {
         await tx.rollback();
     });
 
-    it('La función corrective debería devolver un id cuando se ejecuta correctamente', async() => {
+    it('should return an id when executed correctly', async() => {
         const originalId = 1;
         const invoiceReason = 3;
         const invoiceType = 2;
-        const invoiceClass = 1;
+        const invoiceClass = 8;
         const cloneId = await models.InvoiceIn.corrective(ctx,
             originalId, invoiceReason, invoiceType, invoiceClass, options);
 
@@ -30,7 +30,7 @@ describe('invoiceIn corrective()', () => {
         }, options);
 
         expect(correction.cplusRectificationTypeFk).toEqual(invoiceType);
-        expect(correction.siiTypeInvoiceOutFk).toEqual(invoiceClass);
+        expect(correction.siiTypeInvoiceInFk).toEqual(invoiceClass);
         expect(correction.invoiceCorrectionTypeFk).toEqual(invoiceReason);
     });
 });
diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js
index 48310b32ac..beaa608e6f 100644
--- a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js
+++ b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js
@@ -166,4 +166,21 @@ describe('InvoiceIn filter()', () => {
             throw e;
         }
     });
+
+    it('should return the invoice in matching companyFk', async() => {
+        const tx = await models.InvoiceIn.beginTransaction({});
+        const options = {transaction: tx};
+
+        try {
+            const company = await models.Company.findOne({}, options);
+            const invoicesByCompany = await models.InvoiceIn.find({where: {companyFk: company.id}}, options);
+            const filteredInvoices = await models.InvoiceIn.filter({args: {companyFk: company.id}}, {}, options);
+
+            expect(filteredInvoices.length).toEqual(invoicesByCompany.length);
+            await tx.rollback();
+        } catch (e) {
+            await tx.rollback();
+            throw e;
+        }
+    });
 });
diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js
new file mode 100644
index 0000000000..a83aad3b22
--- /dev/null
+++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js
@@ -0,0 +1,63 @@
+const models = require('vn-loopback/server/server').models;
+
+describe('invoiceIn', () => {
+    let options;
+    let tx;
+    const invoiceId = 1;
+    const supplierId = 791;
+    const currencyId = 1;
+    const companyId = 442;
+
+    beforeEach(async() => {
+        tx = await models.InvoiceIn.beginTransaction({});
+        options = {transaction: tx};
+    });
+
+    afterEach(async() => {
+        await tx.rollback();
+    });
+
+    it('should allow insert for new instance', async() => {
+        const newInvoice = {
+            supplierFk: supplierId,
+            issued: Date.vnNew(),
+            operated: Date.vnNew(),
+            currencyFk: currencyId,
+            companyFk: companyId,
+            isBooked: false
+        };
+
+        const createdInvoice = await models.InvoiceIn.create(newInvoice, options);
+
+        expect(createdInvoice).toBeDefined();
+        expect(createdInvoice.id).toBeDefined();
+    });
+
+    it('should throw an error if trying to update a booked invoice', async() => {
+        const invoice = await models.InvoiceIn.findById(invoiceId, null, options);
+        await invoice.updateAttribute('isBooked', true, options);
+
+        let error;
+        try {
+            await invoice.updateAttribute('supplierFk', supplierId, options);
+        } catch (err) {
+            error = err;
+        }
+
+        expect(error.message).toBe('InvoiceIn is already booked');
+    });
+
+    it('should throw an error if trying to delete a booked invoice', async() => {
+        const invoice = await models.InvoiceIn.findById(invoiceId, null, options);
+        await invoice.updateAttribute('isBooked', true, options);
+
+        let error;
+        try {
+            await models.InvoiceIn.deleteById(invoiceId, options);
+        } catch (err) {
+            error = err;
+        }
+
+        expect(error.message).toBe('InvoiceIn is already booked');
+    });
+});
diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js
new file mode 100644
index 0000000000..e822189bd9
--- /dev/null
+++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js
@@ -0,0 +1,74 @@
+const models = require('vn-loopback/server/server').models;
+
+describe('invoiceInTax', () => {
+    let options;
+    let tx;
+    const invoiceInId = 1;
+    const invoiceInTaxId = 1;
+    beforeEach(async() => {
+        tx = await models.InvoiceInTax.beginTransaction({});
+        options = {transaction: tx};
+    });
+
+    afterEach(async() => {
+        await tx.rollback();
+    });
+
+    it('should throw an error if trying to save a tax from a booked invoice', async() => {
+        const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
+        await invoiceIn.updateAttributes({isBooked: true}, options);
+        const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
+        let error;
+        try {
+            await invoiceInTax.updateAttribute('taxableBase', 100, options);
+        } catch (err) {
+            error = err;
+        }
+
+        expect(error.message).toBe('InvoiceIn is already booked');
+    });
+
+    it('should allow save if the invoice is not booked', async() => {
+        const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
+        await invoiceIn.updateAttribute('isBooked', false, options);
+
+        const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
+        await invoiceInTax.updateAttribute('taxableBase', 100, options);
+
+        const updatedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
+
+        expect(updatedInvoiceInTax.taxableBase).toBe(100);
+    });
+
+    it('should throw an error if trying to delete a tax from a booked invoice', async() => {
+        const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
+        await invoiceIn.updateAttribute('isBooked', true, options);
+
+        let error;
+        try {
+            await models.InvoiceInTax.destroyById(invoiceInTaxId, options);
+        } catch (err) {
+            error = err;
+        }
+
+        expect(error).toBeDefined();
+        expect(error.message).toBe('InvoiceIn is already booked');
+    });
+
+    it('should allow delete if the invoice is not booked', async() => {
+        const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
+        await invoiceIn.updateAttribute('isBooked', false, options);
+
+        let error;
+        try {
+            await models.InvoiceInTax.destroyById(invoiceInTaxId, options);
+        } catch (err) {
+            error = err;
+        }
+
+        const deletedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
+
+        expect(error).toBeUndefined();
+        expect(deletedInvoiceInTax).toBeNull();
+    });
+});
diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js
new file mode 100644
index 0000000000..773e2ac2f6
--- /dev/null
+++ b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js
@@ -0,0 +1,59 @@
+const models = require('vn-loopback/server/server').models;
+
+const invoiceInId = 1;
+const supplierId = 791;
+describe('invoiceIn updateInvoiceIn()', () => {
+    const ctx = beforeAll.getCtx();
+    let options;
+    let tx;
+
+    beforeEach(async() => {
+        options = {transaction: tx};
+        tx = await models.Sale.beginTransaction({});
+        options.transaction = tx;
+    });
+
+    afterEach(async() => {
+        await tx.rollback();
+    });
+
+    it('should update the invoice', async() => {
+        const invoiceBefore = await models.InvoiceIn.findById(invoiceInId, null, options);
+        await update(ctx, options);
+        const invoiceAfter = await models.InvoiceIn.findById(invoiceInId, null, options);
+
+        expect(invoiceAfter.supplierFk).not.toBe(invoiceBefore.supplierFk);
+        expect(invoiceAfter.supplierFk).toBe(supplierId);
+    });
+
+    it('should not update the invoice if is booked', async() => {
+        let error;
+        try {
+            await models.InvoiceIn.toBook(ctx, invoiceInId, options);
+            await update(ctx, options);
+        } catch (e) {
+            error = e;
+        }
+
+        expect(error.message).toBe('InvoiceIn is already booked');
+    });
+});
+
+async function update(ctx, opts) {
+    const supplierRef = 'mockRef';
+    const currencyId = 1;
+    await models.InvoiceIn.updateInvoiceIn(ctx,
+        invoiceInId,
+        supplierId,
+        supplierRef,
+        undefined,
+        undefined,
+        undefined,
+        undefined,
+        undefined,
+        undefined,
+        currencyId,
+        undefined,
+        undefined,
+        opts);
+}
diff --git a/modules/invoiceIn/back/methods/invoice-in/summary.js b/modules/invoiceIn/back/methods/invoice-in/summary.js
index fe198b2b40..b3fd9ee97b 100644
--- a/modules/invoiceIn/back/methods/invoice-in/summary.js
+++ b/modules/invoiceIn/back/methods/invoice-in/summary.js
@@ -37,7 +37,13 @@ module.exports = Self => {
                 {
                     relation: 'supplier',
                     scope: {
-                        fields: ['id', 'name']
+                        fields: ['id', 'name', 'isVies', 'countryFk'],
+                        include: [{
+                            relation: 'country',
+                            scope: {
+                                fields: ['id', 'code']
+                            }
+                        }]
                     }
                 },
                 {
diff --git a/modules/invoiceIn/back/methods/invoice-in/toUnbook.js b/modules/invoiceIn/back/methods/invoice-in/toUnbook.js
index a697e9ddca..c27354d73e 100644
--- a/modules/invoiceIn/back/methods/invoice-in/toUnbook.js
+++ b/modules/invoiceIn/back/methods/invoice-in/toUnbook.js
@@ -52,7 +52,8 @@ module.exports = Self => {
                 accountingEntries = await models.Xdiario.count({ASIEN: asien}, myOptions);
 
                 await models.Xdiario.destroyAll({ASIEN: asien}, myOptions);
-                await Self.updateAll({id: invoiceInId}, {isBooked: false}, myOptions);
+                const invoiceIn = await Self.findById(invoiceInId, myOptions);
+                await invoiceIn.updateAttribute('isBooked', false, myOptions);
             } else {
                 const linkedBookEntry = await models.Xdiario.findOne({
                     fields: ['ASIEN'],
diff --git a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js
index 92a1ba8ee6..2f1b4caca2 100644
--- a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js
+++ b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js
@@ -82,7 +82,7 @@ module.exports = Self => {
 
         try {
             const invoiceIn = await Self.findById(id, null, myOptions);
-            invoiceIn.updateAttributes({supplierFk,
+            await invoiceIn.updateAttributes({supplierFk,
                 supplierRef,
                 issued,
                 operated,
@@ -94,6 +94,7 @@ module.exports = Self => {
                 companyFk,
                 withholdingSageFk
             }, myOptions);
+
             if (tx) await tx.commit();
             return invoiceIn;
         } catch (e) {
diff --git a/modules/invoiceIn/back/models/invoice-in-correction.json b/modules/invoiceIn/back/models/invoice-in-correction.json
index 52e16d4204..d353f9e983 100644
--- a/modules/invoiceIn/back/models/invoice-in-correction.json
+++ b/modules/invoiceIn/back/models/invoice-in-correction.json
@@ -28,11 +28,10 @@
             "model": "InvoiceCorrectionType",
             "foreignKey": "invoiceCorrectionTypeFk"
         },
-        "siiTypeInvoiceOut": {
+        "siiTypeInvoiceIn": {
             "type": "belongsTo",
-            "model": "SiiTypeInvoiceOut",
-            "foreignKey": "siiTypeInvoiceOutFk"
+            "model": "SiiTypeInvoiceIn",
+            "foreignKey": "siiTypeInvoiceInFk"
         }
-
     }
 }
\ No newline at end of file
diff --git a/modules/invoiceIn/back/models/invoice-in-tax.js b/modules/invoiceIn/back/models/invoice-in-tax.js
new file mode 100644
index 0000000000..ce33fe18fb
--- /dev/null
+++ b/modules/invoiceIn/back/models/invoice-in-tax.js
@@ -0,0 +1,18 @@
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+    Self.observe('before save', async function(ctx) {
+        if (ctx.isNewInstance) return;
+
+        const models = Self.app.models;
+        const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk, null, ctx.options);
+        if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
+    });
+
+    Self.observe('before delete', async function(ctx) {
+        const models = Self.app.models;
+        const invoiceInTax = await Self.findById(ctx.where.id, null, ctx.options);
+        const invoiceIn = await models.InvoiceIn.findById(invoiceInTax.invoiceInFk, null, ctx.options);
+        if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
+    });
+};
diff --git a/modules/invoiceIn/back/models/invoice-in-tax.json b/modules/invoiceIn/back/models/invoice-in-tax.json
index 53b5548b63..256ee0553a 100644
--- a/modules/invoiceIn/back/models/invoice-in-tax.json
+++ b/modules/invoiceIn/back/models/invoice-in-tax.json
@@ -22,12 +22,11 @@
             "type": "number"
         },
         "expenseFk": {
-            "type": "number"
+            "type": "string"
         },
         "created": {
             "type": "date"
         }
-
     },
     "relations": {
         "invoiceIn": {
@@ -51,4 +50,4 @@
             "foreignKey": "transactionTypeSageFk"
         }
     }
-}
+}
\ No newline at end of file
diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js
index 1e69c0ef8d..ca506b54d6 100644
--- a/modules/invoiceIn/back/models/invoice-in.js
+++ b/modules/invoiceIn/back/models/invoice-in.js
@@ -19,4 +19,25 @@ module.exports = Self => {
             return new UserError(`This invoice has a linked vehicle.`);
         return err;
     });
+
+    Self.observe('before save', async function(ctx) {
+        if (ctx.isNewInstance) return;
+
+        const changes = ctx.data || ctx.instance;
+        const orgData = ctx.currentInstance;
+        let isNotEditable = orgData.isBooked || (!orgData.isBooked && changes.isBooked);
+
+        if (isNotEditable) {
+            for (const [key, value] of Object.entries(changes)) {
+                if (key !== 'isBooked' && value !== orgData[key])
+                    throw new UserError('InvoiceIn is already booked');
+            }
+        }
+    });
+
+    Self.observe('before delete', async function(ctx) {
+        const invoiceIn = await Self.findById(ctx.where.id, null, ctx.options);
+        if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
+    });
 };
+
diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js
index 5526d214ad..7befdcbeb9 100644
--- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js
+++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js
@@ -1,3 +1,5 @@
+const UserError = require('vn-loopback/util/user-error');
+
 module.exports = Self => {
     Self.remoteMethodCtx('clientsToInvoice', {
         description: 'Get the clients to make global invoicing',
@@ -47,7 +49,12 @@ module.exports = Self => {
         }
 
         try {
-            // Packaging liquidation
+            const clientCanBeInvoiced =
+                await Self.app.models.Client.canBeInvoiced(clientId, companyFk, myOptions);
+
+            if (!clientCanBeInvoiced)
+                throw new UserError(`This client can't be invoiced`);
+
             const vIsAllInvoiceable = false;
             await Self.rawSql('CALL ticketPackaging_add(?, ?, ?, ?)', [
                 clientId,
@@ -71,9 +78,6 @@ module.exports = Self => {
                         AND t.shipped BETWEEN ? AND util.dayEnd(?)
                         AND (t.clientFk = ? OR ? IS NULL )
                         AND t.companyFk = ?
-                        AND c.hasToInvoice
-                        AND c.isTaxDataChecked
-                        AND c.isActive
                         AND NOT t.isDeleted
                     GROUP BY IF(c.hasToInvoiceByAddress, a.id, c.id)
                     HAVING SUM(t.totalWithVat) > 0;`;
diff --git a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js
index dcc1fa6e80..493f19aa77 100644
--- a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js
+++ b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js
@@ -7,7 +7,12 @@ module.exports = Self => {
                 arg: 'companyFk',
                 type: 'number',
                 required: true
-            }
+            },
+            {
+                arg: 'serialType',
+                type: 'string',
+                required: true
+            },
         ],
         returns: {
             type: ['object'],
@@ -19,16 +24,16 @@ module.exports = Self => {
         }
     });
 
-    Self.getInvoiceDate = async companyFk => {
+    Self.getInvoiceDate = async(companyFk, serialType) => {
         const models = Self.app.models;
         const [invoiceDate] = await models.InvoiceOut.rawSql(
             `SELECT MAX(io.issued) issued
                 FROM invoiceOut io
                     JOIN invoiceOutSerial ios ON ios.code = io.serial
-                WHERE ios.type = 'global'
-                    AND io.issued 
+                WHERE ios.type = ?
+                    AND io.issued
                     AND io.companyFk = ?`,
-            [companyFk]
+            [serialType, companyFk]
         );
         return invoiceDate;
     };
diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js
index 470690c5a4..df0566c540 100644
--- a/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js
+++ b/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js
@@ -4,11 +4,11 @@ describe('InvoiceOut clientsToInvoice()', () => {
     const userId = 1;
     const clientId = 1101;
     const companyFk = 442;
-    const maxShipped = new Date();
+    const maxShipped = Date.vnNew();
     maxShipped.setMonth(11);
     maxShipped.setDate(31);
     maxShipped.setHours(23, 59, 59, 999);
-    const invoiceDate = new Date();
+    const invoiceDate = Date.vnNew();
     const activeCtx = {
         getLocale: () => {
             return 'en';
diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/getInvoiceDate.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/getInvoiceDate.spec.js
new file mode 100644
index 0000000000..8304022509
--- /dev/null
+++ b/modules/invoiceOut/back/methods/invoiceOut/specs/getInvoiceDate.spec.js
@@ -0,0 +1,39 @@
+const models = require('vn-loopback/server/server').models;
+const moment = require('moment');
+
+describe('getInvoiceDate()', () => {
+    const companyFk = 442;
+    let tx;
+    let options;
+
+    beforeEach(async() => {
+        tx = await models.InvoiceOut.beginTransaction({});
+        options = {transaction: tx};
+    });
+
+    afterEach(async() => {
+        await tx.rollback();
+    });
+
+    it('should return a correct date for serialType "global"', async() => {
+        const serialType = 'global';
+        const result = await models.InvoiceOut.getInvoiceDate(companyFk, serialType, options);
+
+        expect(moment(result.issued).format('YYYY-MM-DD')).toEqual('2000-12-01');
+    });
+
+    it('should return null for serialType "multiple"', async() => {
+        const serialType = 'multiple';
+        const result = await models.InvoiceOut.getInvoiceDate(companyFk, serialType, options);
+
+        expect(result.issued).toBeNull();
+    });
+
+    it('should return correct date for serialType "quick"', async() => {
+        const serialType = 'quick';
+        const result = await models.InvoiceOut.getInvoiceDate(companyFk, serialType, options);
+
+        expect(moment(result.issued).format('YYYY-MM-DD')).toEqual('2001-01-01');
+    });
+});
+
diff --git a/modules/invoiceOut/back/model-config.json b/modules/invoiceOut/back/model-config.json
index 9c7512429f..710d824c3a 100644
--- a/modules/invoiceOut/back/model-config.json
+++ b/modules/invoiceOut/back/model-config.json
@@ -43,5 +43,8 @@
     },
     "SiiTypeInvoiceOut": {
         "dataSource": "vn"
+    },
+    "SiiTypeInvoiceIn": {
+        "dataSource": "vn"
     }
-}
+}
\ No newline at end of file
diff --git a/modules/invoiceOut/back/models/sii-type-invoice-in.json b/modules/invoiceOut/back/models/sii-type-invoice-in.json
new file mode 100644
index 0000000000..a191febb99
--- /dev/null
+++ b/modules/invoiceOut/back/models/sii-type-invoice-in.json
@@ -0,0 +1,22 @@
+{
+    "name": "SiiTypeInvoiceIn",
+    "base": "VnModel",
+    "options": {
+        "mysql": {
+            "table": "siiTypeInvoiceIn"
+        }
+    },
+    "properties": {
+        "id": {
+            "id": true,
+            "type": "number",
+            "description": "Identifier"
+        },
+        "code": {
+            "type": "string"
+        },
+        "description": {
+            "type": "string"
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/invoiceOut/back/models/sii-type-invoice-out.json b/modules/invoiceOut/back/models/sii-type-invoice-out.json
index 37fd39c38f..89f01bd749 100644
--- a/modules/invoiceOut/back/models/sii-type-invoice-out.json
+++ b/modules/invoiceOut/back/models/sii-type-invoice-out.json
@@ -17,9 +17,6 @@
         },
         "description": {
             "type": "string"
-        },
-        "code": {
-            "type": "string"
         }
     }
-}
+}
\ No newline at end of file
diff --git a/modules/item/back/methods/item/lastEntriesFilter.js b/modules/item/back/methods/item/lastEntriesFilter.js
index 5aafbb4f65..b038bb155b 100644
--- a/modules/item/back/methods/item/lastEntriesFilter.js
+++ b/modules/item/back/methods/item/lastEntriesFilter.js
@@ -29,10 +29,12 @@ module.exports = Self => {
             Object.assign(myOptions, options);
 
         const stmt = new ParameterizedSQL(
-            `SELECT w.id AS warehouseFk,
-                    w.name AS warehouse,
-                    tr.landed,
-                    b.id AS buyFk,
+            `SELECT i.id itemFk,
+                    w.id warehouseFk,
+                    w.name warehouse,
+                    CAST(tr.landed AS CHAR) landed,
+                    tr.landed landedDate,
+                    b.id buyFk,
                     b.entryFk,
                     b.isIgnored,
                     b.price2, 
@@ -47,14 +49,18 @@ module.exports = Self => {
                     b.buyingValue + 
                         b.freightValue + 
                         b.comissionValue + 
-                        b.packageValue AS cost,
+                        b.packageValue cost,
                     b.buyingValue,
                     b.freightValue,
                     b.comissionValue,
                     b.packageValue,
                     b.packagingFk ,
-                    s.id AS supplierFk,
-                    s.name AS supplier
+                    s.id supplierFk,
+                    s.name supplier,
+                    b.printedStickers,
+                    c.inventoried,
+                    ic.supplierFk inventorySupplierFk,
+                    s.id = ic.supplierFk isInventorySupplier
                 FROM itemType it
                     RIGHT JOIN (entry e 
                         LEFT JOIN supplier s ON s.id = e.supplierFk
@@ -65,9 +71,14 @@ module.exports = Self => {
                         LEFT JOIN warehouse w ON w.id = tr.warehouseInFk
                         LEFT JOIN origin o ON o.id = i.originFk
                         ) ON it.id = i.typeFk
-                LEFT JOIN edi.ekt ek ON b.ektFk = ek.id`
+                    LEFT JOIN edi.ekt ek ON b.ektFk = ek.id
+                    JOIN config c
+                    JOIN inventoryConfig ic`
         );
-        stmt.merge(conn.makeSuffix(filter));
+
+        stmt.merge(conn.makeWhere(filter.where));
+        stmt.merge('AND IF(s.id = ic.supplierFk, tr.landed = DATE(c.inventoried), TRUE)');
+        stmt.merge(conn.makePagination(filter));
 
         return conn.executeStmt(stmt, myOptions);
     };
diff --git a/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js b/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js
index 2fd30c2ca8..b2bfdf59c4 100644
--- a/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js
+++ b/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js
@@ -1,16 +1,22 @@
 const {models} = require('vn-loopback/server/server');
+const itemFk = 1;
+
+const today = Date.vnNew();
+today.setHours(23, 59, 59, 999);
+
+const twoMonthsAgo = Date.vnNew();
+twoMonthsAgo.setHours(0, 0, 0, 0);
+twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - 2, 1);
 describe('item lastEntriesFilter()', () => {
     it('should return two entry for the given item', async() => {
         const minDate = Date.vnNew();
         minDate.setHours(0, 0, 0, 0);
-        const maxDate = Date.vnNew();
-        maxDate.setHours(23, 59, 59, 59);
 
         const tx = await models.Item.beginTransaction({});
         const options = {transaction: tx};
 
         try {
-            const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
+            const filter = {where: {itemFk, landed: {between: [minDate, today]}}};
             const result = await models.Item.lastEntriesFilter(filter, options);
 
             expect(result.length).toEqual(2);
@@ -23,21 +29,61 @@ describe('item lastEntriesFilter()', () => {
     });
 
     it('should return six entries for the given item', async() => {
-        const minDate = Date.vnNew();
-        minDate.setHours(0, 0, 0, 0);
-        minDate.setMonth(minDate.getMonth() - 2, 1);
-
-        const maxDate = Date.vnNew();
-        maxDate.setHours(23, 59, 59, 59);
-
         const tx = await models.Item.beginTransaction({});
         const options = {transaction: tx};
 
         try {
-            const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
+            const filter = {where: {itemFk, landed: {between: [twoMonthsAgo, today]}}};
+            const result = await models.Item.lastEntriesFilter(filter, options);
+            const twoMonthsAgoUtc = twoMonthsAgo.getTime();
+            const todayUtc = today.getTime();
+
+            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 = Date.vnNew(item.landed).getTime();
+                        const isLandedValid = landedDate >= twoMonthsAgoUtc && landedDate <= todayUtc;
+
+                        return isItemFkValid && isLandedValid;
+                    })
+                )
+            ).filter(Boolean).length;
+
+            expect(result.length).toEqual(resultMatch);
+
+            await tx.rollback();
+        } catch (e) {
+            await tx.rollback();
+            throw e;
+        }
+    });
+
+    it('should return just the inventoried inventory', async() => {
+        const tx = await models.Item.beginTransaction({});
+        const options = {transaction: tx};
+
+        try {
+            const filter = {where: {itemFk, landed: {between: [twoMonthsAgo, today]}}};
             const result = await models.Item.lastEntriesFilter(filter, options);
 
-            expect(result.length).toEqual(6);
+            const {supplierFk} = await models.InventoryConfig.findOne(options);
+            const {inventoried} = await models.Config.findOne(options);
+
+            let hasInventoriedDate = false;
+            result.forEach(entry => {
+                if (entry.supplierFk === supplierFk &&
+                    entry.landedDate.getTime() === inventoried.getTime()
+                )hasInventoriedDate = true;
+            });
+
+            expect(hasInventoriedDate).toEqual(true);
 
             await tx.rollback();
         } catch (e) {
diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json
index eda56e9385..1598834551 100644
--- a/modules/item/back/models/item.json
+++ b/modules/item/back/models/item.json
@@ -154,6 +154,9 @@
         },
         "photoMotivation": {
             "type": "string"
+        },
+        "isCustomInspectionRequired": {
+            "type": "boolean"
         }
     },
     "relations": {
@@ -222,4 +225,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js
index a681ebc836..ac8a722bd2 100644
--- a/modules/monitor/back/methods/sales-monitor/salesFilter.js
+++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js
@@ -89,10 +89,20 @@ 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',
                 description: 'The country id filter'
+            },
+            {
+                arg: 'payMethod',
+                type: 'string',
+                description: 'The payment method filter'
             }
         ],
         returns: {
@@ -160,6 +170,8 @@ module.exports = Self => {
             case 'clientFk':
                 param = `t.${param}`;
                 return {[param]: value};
+            case 'payMethod':
+                return {'c.payMethodFk': value};
             }
         });
 
@@ -174,7 +186,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 +212,20 @@ module.exports = Self => {
                     u.name userName,
                     c.salesPersonFk,
                     c.credit,
+                    c.payMethodFk payMethodFk,
+                    pm.id payMethodId,
+                    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 +239,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 +387,7 @@ module.exports = Self => {
                 }
             case 'agencyModeFk':
             case 'warehouseFk':
+            case 'packing':
             case 'countryFk':
                 param = `f.${param}`;
                 return {[param]: value};
diff --git a/modules/route/back/methods/route/optimizePriority.js b/modules/route/back/methods/route/optimizePriority.js
new file mode 100644
index 0000000000..56db4ffb57
--- /dev/null
+++ b/modules/route/back/methods/route/optimizePriority.js
@@ -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;
+        }
+    };
+};
diff --git a/modules/route/back/methods/route/specs/optimizePriority.spec.js b/modules/route/back/methods/route/specs/optimizePriority.spec.js
new file mode 100644
index 0000000000..c1c2dc45e2
--- /dev/null
+++ b/modules/route/back/methods/route/specs/optimizePriority.spec.js
@@ -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');
+    });
+});
diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js
index cd8685cec0..f73ff3e51d 100644
--- a/modules/route/back/models/route.js
+++ b/modules/route/back/models/route.js
@@ -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);
 };
diff --git a/modules/ticket/back/methods/expedition/filter.js b/modules/ticket/back/methods/expedition/filter.js
index 43be143492..801d00a9bf 100644
--- a/modules/ticket/back/methods/expedition/filter.js
+++ b/modules/ticket/back/methods/expedition/filter.js
@@ -49,7 +49,9 @@ module.exports = Self => {
                         es.workerFk expeditionScanWorkerFk,
                         su.name scannerUserName,
                         es.scanned,
-                        est.description state
+                        est.description state,
+                        de.longName,
+                        de.itemFk
                     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 +61,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));
diff --git a/modules/ticket/back/methods/sale/updateQuantity.js b/modules/ticket/back/methods/sale/updateQuantity.js
index 36d75ffedf..4de1bcbd65 100644
--- a/modules/ticket/back/methods/sale/updateQuantity.js
+++ b/modules/ticket/back/methods/sale/updateQuantity.js
@@ -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`,
                 });
 
diff --git a/modules/ticket/back/methods/ticket-request/confirm.js b/modules/ticket/back/methods/ticket-request/confirm.js
index 7c17d00106..45ee287dee 100644
--- a/modules/ticket/back/methods/ticket-request/confirm.js
+++ b/modules/ticket/back/methods/ticket-request/confirm.js
@@ -54,9 +54,17 @@ module.exports = Self => {
                 throw new UserError(`That item doesn't exists`);
 
             const request = await models.TicketRequest.findById(ctx.args.id, {
-                include: {relation: 'ticket'}
+                include: {
+                    relation: 'ticket',
+                    scope: {
+                        include: {
+                            relation: 'client',
+                            scope: {
+                                fields: ['id', 'name', 'salesPersonFk']
+                            }
+                        }
+                    }}
             }, myOptions);
-
             const itemStock = await models.Item.getVisibleAvailable(
                 ctx.args.itemFk,
                 request.ticket().warehouseFk,
@@ -89,19 +97,19 @@ module.exports = Self => {
             const query = `CALL vn.sale_calculateComponent(?, NULL)`;
             await Self.rawSql(query, [sale.id], myOptions);
 
-            const url = await Self.app.models.Url.getUrl();
-            const requesterId = request.requesterFk;
-
-            const message = $t('Bought units from buy request', {
-                quantity: sale.quantity,
-                concept: sale.concept,
-                itemId: sale.itemFk,
-                ticketId: sale.ticketFk,
-                url: `${url}ticket/${sale.ticketFk}/summary`,
-                urlItem: `${url}item/${sale.itemFk}/summary`
-            });
-            await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions);
-
+            const salesPerson = request.ticket().client().salesPersonFk;
+            if (salesPerson) {
+                const url = await Self.app.models.Url.getUrl();
+                const message = $t('Bought units from buy request', {
+                    quantity: sale.quantity,
+                    concept: sale.concept,
+                    itemId: sale.itemFk,
+                    ticketId: sale.ticketFk,
+                    url: `${url}ticket/${sale.ticketFk}/summary`,
+                    urlItem: `${url}item/${sale.itemFk}/summary`
+                });
+                await models.Chat.sendCheckingPresence(ctx, salesPerson, message, myOptions);
+            }
             if (tx) await tx.commit();
 
             return sale;
diff --git a/modules/ticket/back/methods/ticket-request/deny.js b/modules/ticket/back/methods/ticket-request/deny.js
index 44f1e48a1e..26e6f63ff9 100644
--- a/modules/ticket/back/methods/ticket-request/deny.js
+++ b/modules/ticket/back/methods/ticket-request/deny.js
@@ -1,18 +1,22 @@
+const UserError = require('vn-loopback/util/user-error');
 module.exports = Self => {
     Self.remoteMethodCtx('deny', {
-        description: 'sets a ticket request to denied and returns the changes',
+        description: 'Sets a ticket request to denied and returns the changes',
         accessType: 'WRITE',
-        accepts: [{
-            arg: 'id',
-            type: 'number',
-            required: true,
-            description: 'The request ID',
-        }, {
-            arg: 'observation',
-            type: 'String',
-            required: true,
-            description: 'The request observation',
-        }],
+        accepts: [
+            {
+                arg: 'id',
+                type: 'number',
+                required: true,
+                description: 'The request ID',
+            },
+            {
+                arg: 'observation',
+                type: 'string',
+                required: true,
+                description: 'The request observation',
+            }
+        ],
         returns: {
             type: 'number',
             root: true
@@ -29,7 +33,7 @@ module.exports = Self => {
         const myOptions = {};
         let tx;
 
-        if (typeof options == 'object')
+        if (typeof options === 'object')
             Object.assign(myOptions, options);
 
         if (!myOptions.transaction) {
@@ -39,7 +43,7 @@ module.exports = Self => {
 
         try {
             const userId = ctx.req.accessToken.userId;
-            const worker = await Self.app.models.Worker.findOne({where: {id: userId}}, myOptions);
+            const worker = await models.Worker.findById(userId, {fields: ['id']}, myOptions);
 
             const params = {
                 isOk: false,
@@ -47,19 +51,32 @@ module.exports = Self => {
                 response: ctx.args.observation,
             };
 
-            const request = await Self.app.models.TicketRequest.findById(ctx.args.id, null, myOptions);
-            await request.updateAttributes(params, myOptions);
+            const request = await models.TicketRequest.findById(ctx.args.id, {
+                include: {
+                    relation: 'ticket',
+                    scope: {
+                        include: {
+                            relation: 'client',
+                            scope: {
+                                fields: ['id', 'name', 'salesPersonFk']
+                            }
+                        }
+                    }
+                }
+            }, myOptions);
 
-            const url = await Self.app.models.Url.getUrl();
-            const requesterId = request.requesterFk;
+            const salesPerson = request.ticket().client().salesPersonFk;
+            if (salesPerson) {
+                const url = await models.Url.getUrl();
+                const message = $t('Deny buy request', {
+                    ticketId: request.ticketFk,
+                    url: `${url}ticket/${request.ticketFk}/request/index`,
+                    observation: params.response
+                });
 
-            const message = $t('Deny buy request', {
-                ticketId: request.ticketFk,
-                url: `${url}ticket/${request.ticketFk}/request/index`,
-                observation: params.response
-            });
-
-            await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions);
+                await models.Chat.sendCheckingPresence(ctx, salesPerson, message, myOptions);
+                await request.updateAttributes(params, myOptions);
+            }
 
             if (tx) await tx.commit();
 
diff --git a/modules/ticket/back/methods/ticket-request/filter.js b/modules/ticket/back/methods/ticket-request/filter.js
index 53f90b98f6..c2edcae81a 100644
--- a/modules/ticket/back/methods/ticket-request/filter.js
+++ b/modules/ticket/back/methods/ticket-request/filter.js
@@ -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;
diff --git a/modules/ticket/back/methods/ticket/getTicketsAdvance.js b/modules/ticket/back/methods/ticket/getTicketsAdvance.js
index 41f3ee79a5..58d46173ca 100644
--- a/modules/ticket/back/methods/ticket/getTicketsAdvance.js
+++ b/modules/ticket/back/methods/ticket/getTicketsAdvance.js
@@ -55,6 +55,11 @@ module.exports = Self => {
                 type: 'number',
                 description: 'Department identifier'
             },
+            {
+                arg: 'onlyWithDestination',
+                type: 'Boolean',
+                description: 'True when only tickets with destination are returned'
+            },
             {
                 arg: 'filter',
                 type: 'object',
@@ -103,6 +108,8 @@ module.exports = Self => {
                 return {'f.isFullMovable': value};
             case 'departmentFk':
                 return {'f.departmentFk': value};
+            case 'onlyWithDestination':
+                return {'f.id': value ? {neq: null} : null};
             }
         });
 
diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js
index a941013cd4..157cdb1ff3 100644
--- a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js
@@ -8,6 +8,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
     tomorrow.setDate(today.getDate() + 1);
     const salesDeptId = 43;
     const spain1DeptId = 95;
+    const warehouseId = 1;
     beforeAll.mockLoopBackContext();
 
     it('should return the tickets passing the required data', async() => {
@@ -19,7 +20,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
             const args = {
                 dateFuture: tomorrow,
                 dateToAdvance: today,
-                warehouseFk: 1,
+                warehouseFk: warehouseId,
             };
 
             ctx.args = args;
@@ -42,7 +43,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
             const args = {
                 dateFuture: tomorrow,
                 dateToAdvance: today,
-                warehouseFk: 1,
+                warehouseFk: warehouseId,
                 isFullMovable: true
             };
 
@@ -67,7 +68,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
             const args = {
                 dateFuture: tomorrow,
                 dateToAdvance: today,
-                warehouseFk: 1,
+                warehouseFk: warehouseId,
                 isFullMovable: false
             };
 
@@ -92,7 +93,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
             const args = {
                 dateFuture: tomorrow,
                 dateToAdvance: today,
-                warehouseFk: 1,
+                warehouseFk: warehouseId,
                 ipt: 'V'
             };
 
@@ -117,7 +118,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
             const args = {
                 dateFuture: tomorrow,
                 dateToAdvance: today,
-                warehouseFk: 1,
+                warehouseFk: warehouseId,
                 tfIpt: 'V'
             };
 
@@ -141,7 +142,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
             ctx.args = {
                 dateFuture: tomorrow,
                 dateToAdvance: today,
-                warehouseFk: 1,
+                warehouseFk: warehouseId,
             };
 
             await models.Ticket.updateAll({id: {inq: [12, 31]}}, {clientFk: 1}, options);
@@ -167,4 +168,56 @@ describe('TicketFuture getTicketsAdvance()', () => {
             throw e;
         }
     });
+
+    it('should return the tickets with only destination', async() => {
+        const tx = await models.Ticket.beginTransaction({});
+
+        try {
+            const options = {transaction: tx};
+
+            const args = {
+                dateFuture: today,
+                dateToAdvance: today.setHours(23, 59, 59, 999),
+                warehouseFk: warehouseId,
+            };
+            ctx.args = args;
+
+            const allTickets = await models.Ticket.getTicketsAdvance(ctx, options);
+            ctx.args.onlyWithDestination = true;
+            const withDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options);
+
+            expect(allTickets.filter(ticket => ticket.id).length).toBe(withDestinationTickets.length);
+
+            await tx.rollback();
+        } catch (e) {
+            await tx.rollback();
+            throw e;
+        }
+    });
+
+    it('should return the tickets without only destination', async() => {
+        const tx = await models.Ticket.beginTransaction({});
+
+        try {
+            const options = {transaction: tx};
+
+            const args = {
+                dateFuture: today,
+                dateToAdvance: today.setHours(23, 59, 59, 999),
+                warehouseFk: warehouseId,
+            };
+            ctx.args = args;
+
+            const allTickets = await models.Ticket.getTicketsAdvance(ctx, options);
+            ctx.args.onlyWithDestination = false;
+            const withoutDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options);
+
+            expect(allTickets.filter(ticket => !ticket.id).length).toBe(withoutDestinationTickets.length);
+
+            await tx.rollback();
+        } catch (e) {
+            await tx.rollback();
+            throw e;
+        }
+    });
 });
diff --git a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js
index 88812dc923..f9e4bcac0d 100644
--- a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js
@@ -77,6 +77,8 @@ describe('ticket makeInvoice()', () => {
             await tx.rollback();
         }
 
-        expect(error.message).toEqual(`The address of the customer must have information about Incoterms and Customs Agent`);
+        expect(error.message).toEqual(
+            `The address of the customer must have information about Incoterms and Customs Agent`
+        );
     });
 });
diff --git a/modules/travel/back/methods/travel/extraCommunityFilter.js b/modules/travel/back/methods/travel/extraCommunityFilter.js
index f1586f804d..2f3f998d6e 100644
--- a/modules/travel/back/methods/travel/extraCommunityFilter.js
+++ b/modules/travel/back/methods/travel/extraCommunityFilter.js
@@ -132,18 +132,18 @@ module.exports = Self => {
                     CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) loadedKg,
                     CAST(
                         SUM(
-                            vc.aerealVolumetricDensity * 
-                            b.stickers * 
+                            vc.aerealVolumetricDensity *
+                            b.stickers *
                             IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000
                         ) AS DECIMAL(10,0)
                     ) volumeKg,
                     CAST(
                         GREATEST(
                             SUM(b.weight * b.stickers) ,
-                            SUM(vc.aerealVolumetricDensity * 
-                                b.stickers * 
-                                IF(pkg.volume, 
-                                    pkg.volume, 
+                            SUM(vc.aerealVolumetricDensity *
+                                b.stickers *
+                                IF(pkg.volume,
+                                    pkg.volume,
                                     pkg.width * pkg.depth * pkg.height) / 1000000)
                         ) / t.kg * 100 AS INT
                     ) percentageKg
@@ -185,11 +185,12 @@ module.exports = Self => {
                     CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg,
                     CAST(
                         SUM(
-                            vc.aerealVolumetricDensity * 
-                            b.stickers * 
+                            vc.aerealVolumetricDensity *
+                            b.stickers *
                             IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000
                         ) AS DECIMAL(10,0)
-                    ) as volumeKg
+                    ) as volumeKg,
+                    MAX(i.isCustomInspectionRequired) isCustomInspectionRequired
                 FROM tmp.travel tr
                     JOIN entry e ON e.travelFk = tr.id
                     JOIN buy b ON b.entryFk = e.id
diff --git a/modules/travel/back/methods/travel/filter.js b/modules/travel/back/methods/travel/filter.js
index b968739258..30c1a45fad 100644
--- a/modules/travel/back/methods/travel/filter.js
+++ b/modules/travel/back/methods/travel/filter.js
@@ -83,6 +83,14 @@ module.exports = Self => {
                 arg: 'daysOnward',
                 type: 'number',
                 description: 'The days onward'
+            }, {
+                arg: 'shipped',
+                type: 'date',
+                description: 'The shipped date'
+            }, {
+                arg: 'landed',
+                type: 'date',
+                description: 'The landed date'
             }
         ],
         returns: {
@@ -108,6 +116,10 @@ module.exports = Self => {
                     : {'t.ref': {like: `%${value}%`}};
             case 'ref':
                 return {'t.ref': {like: `%${value}%`}};
+            case 'shipped':
+                return {'t.shipped': value};
+            case 'landed':
+                return {'t.landed': value};
             case 'shippedFrom':
                 return {'t.shipped': {gte: value}};
             case 'shippedTo':
diff --git a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js
index 7e90c76817..8fa013fe4b 100644
--- a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js
+++ b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js
@@ -112,4 +112,17 @@ describe('Travel extraCommunityFilter()', () => {
 
         expect(result.length).toEqual(2);
     });
+
+    it('should return field isCustomInspectionRequired true', async() => {
+        const ctx = {
+            args: {
+                id: 2
+            }
+        };
+
+        const result = await app.models.Travel.extraCommunityFilter(ctx, filter);
+
+        expect(result[0].entries[0].isCustomInspectionRequired).toBeTruthy();
+        expect(result[0].entries[1].isCustomInspectionRequired).toBeFalsy();
+    });
 });
diff --git a/modules/travel/back/methods/travel/specs/getEntries.spec.js b/modules/travel/back/methods/travel/specs/getEntries.spec.js
index fcaa80d02b..9286a9d556 100644
--- a/modules/travel/back/methods/travel/specs/getEntries.spec.js
+++ b/modules/travel/back/methods/travel/specs/getEntries.spec.js
@@ -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);
     });
 
diff --git a/modules/worker/back/methods/worker/createAbsence.js b/modules/worker/back/methods/worker/createAbsence.js
index e46ce95775..93ca7fd895 100644
--- a/modules/worker/back/methods/worker/createAbsence.js
+++ b/modules/worker/back/methods/worker/createAbsence.js
@@ -128,7 +128,10 @@ module.exports = Self => {
             const account = await models.VnUser.findById(userId, null, myOptions);
             const subordinated = await models.VnUser.findById(id, null, myOptions);
             const worker = await models.Worker.findById(subordinated.id, null, myOptions);
-            const departmentBoss = await models.VnUser.findById(worker.bossFk, null, myOptions);
+            const receiver = await models.EmailUser.findOne({
+                fields: ['email'],
+                where: {userFk: worker.bossFk}
+            }, myOptions);
             const url = await Self.app.models.Url.getUrl();
             const body = $t('Created absence', {
                 author: account.nickname,
@@ -140,7 +143,7 @@ module.exports = Self => {
             await models.Mail.create({
                 subject: $t('Absence change notification on the labour calendar'),
                 body: body,
-                receiver: departmentBoss.email
+                receiver: receiver.email
             }, myOptions);
 
             if (tx) await tx.commit();
diff --git a/modules/worker/back/models/device-production-user.json b/modules/worker/back/models/device-production-user.json
index a024cc94c8..31aaf92d4f 100644
--- a/modules/worker/back/models/device-production-user.json
+++ b/modules/worker/back/models/device-production-user.json
@@ -25,7 +25,7 @@
         "userFk": {
             "type": "number"
         },
-        "simSerialNumber": {
+        "simFk": {
             "type": "string"
         },
         "created": {
diff --git a/modules/worker/back/models/worker-irpf.json b/modules/worker/back/models/worker-irpf.json
index 65f72a1fde..eafda05964 100644
--- a/modules/worker/back/models/worker-irpf.json
+++ b/modules/worker/back/models/worker-irpf.json
@@ -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": {
diff --git a/modules/zone/back/methods/zone/deleteZone.js b/modules/zone/back/methods/zone/deleteZone.js
index e2e01a949d..a147ee5885 100644
--- a/modules/zone/back/methods/zone/deleteZone.js
+++ b/modules/zone/back/methods/zone/deleteZone.js
@@ -51,7 +51,7 @@ module.exports = Self => {
             };
 
             const ticketList = await models.Ticket.find(filter, myOptions);
-            const hasRefFk = ticketList.some(ticket => ticket.refFk);
+            const hasRefFk = ticketList.some(ticket => !ticket.refFk);
             if (hasRefFk)
                 throw new UserError('There are tickets to be invoiced');
 
diff --git a/modules/zone/back/model-config.json b/modules/zone/back/model-config.json
index 3bbbe0d1b3..2cd3f9d019 100644
--- a/modules/zone/back/model-config.json
+++ b/modules/zone/back/model-config.json
@@ -17,6 +17,9 @@
     "ZoneClosure": {
         "dataSource": "vn"
     },
+    "ZoneConfig": {
+        "dataSource": "vn"
+    },
     "ZoneEvent": {
         "dataSource": "vn"
     },
diff --git a/modules/zone/back/models/zone-config.json b/modules/zone/back/models/zone-config.json
new file mode 100644
index 0000000000..a5da7fe557
--- /dev/null
+++ b/modules/zone/back/models/zone-config.json
@@ -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"
+		}
+	}
+}
diff --git a/modules/zone/back/models/zone.js b/modules/zone/back/models/zone.js
index 6d5a6cdca9..7b5cb43011 100644
--- a/modules/zone/back/models/zone.js
+++ b/modules/zone/back/models/zone.js
@@ -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();
+    }
 };
diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json
index 5b25e40d1b..141b287501 100644
--- a/modules/zone/back/models/zone.json
+++ b/modules/zone/back/models/zone.json
@@ -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"
+		}
+	}
 }
diff --git a/package.json b/package.json
index 4e823eaad4..a843ac9c57 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "salix-back",
-    "version": "24.52.0",
+    "version": "25.02.0",
     "author": "Verdnatura Levante SL",
     "description": "Salix backend",
     "license": "GPL-3.0",
diff --git a/print/templates/email/incoterms-authorization/locale/en.yml b/print/templates/email/incoterms-authorization/locale/en.yml
new file mode 100644
index 0000000000..7e14025758
--- /dev/null
+++ b/print/templates/email/incoterms-authorization/locale/en.yml
@@ -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!
diff --git a/print/templates/reports/balance-compensation/locale/en.yml b/print/templates/reports/balance-compensation/locale/en.yml
new file mode 100644
index 0000000000..8241274820
--- /dev/null
+++ b/print/templates/reports/balance-compensation/locale/en.yml
@@ -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,
diff --git a/print/templates/reports/incoterms-authorization/locale/en.yml b/print/templates/reports/incoterms-authorization/locale/en.yml
new file mode 100644
index 0000000000..eb6a8a5138
--- /dev/null
+++ b/print/templates/reports/incoterms-authorization/locale/en.yml
@@ -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'