#2687 - Travel CloneWithEntries #1887
|
@ -0,0 +1,3 @@
|
|||
GRANT EXECUTE ON PROCEDURE util.tx_commit TO guest;
|
||||
GRANT EXECUTE ON PROCEDURE util.tx_rollback TO guest;
|
||||
GRANT EXECUTE ON PROCEDURE util.tx_start TO guest;
|
|
@ -0,0 +1,85 @@
|
|||
DROP PROCEDURE IF EXISTS vn.travel_cloneWithEntries;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`travel_cloneWithEntries`(
|
||||
IN vTravelFk INT,
|
||||
IN vDateStart DATE,
|
||||
IN vDateEnd DATE,
|
||||
IN vWarehouseOutFk INT,
|
||||
IN vWarehouseInFk INT,
|
||||
IN vRef VARCHAR(255),
|
||||
IN vAgencyModeFk INT,
|
||||
OUT vNewTravelFk INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Clona un travel junto con sus entradas y compras
|
||||
* @param vTravelFk travel plantilla a clonar
|
||||
* @param vDateStart fecha del shipment del nuevo travel
|
||||
* @param vDateEnd fecha del landing del nuevo travel
|
||||
* @param vWarehouseOutFk warehouse del salida del nuevo travel
|
||||
* @param vWarehouseInFk warehouse de landing del nuevo travel
|
||||
* @param vRef referencia del nuevo travel
|
||||
* @param vAgencyModeFk del nuevo travel
|
||||
* @param vNewTravelFk id del nuevo travel
|
||||
*/
|
||||
DECLARE vNewEntryFk INT;
|
||||
DECLARE vEvaNotes VARCHAR(255);
|
||||
DECLARE vDone BOOL;
|
||||
DECLARE vAuxEntryFk INT;
|
||||
DECLARE vTx BOOLEAN DEFAULT !@@in_transaction;
|
||||
DECLARE vRsEntry CURSOR FOR
|
||||
SELECT e.id
|
||||
FROM entry e
|
||||
JOIN travel t ON t.id = e.travelFk
|
||||
WHERE e.travelFk = vTravelFk;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
CALL util.tx_rollback(vTx);
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
CALL util.tx_start(vTx);
|
||||
|
||||
INSERT INTO travel (shipped, landed, warehouseInFk, warehouseOutFk, agencyModeFk, `ref`, isDelivered, isReceived, m3, cargoSupplierFk, kg,clonedFrom)
|
||||
SELECT vDateStart, vDateEnd, vWarehouseInFk, vWarehouseOutFk, vAgencyModeFk, vRef, isDelivered, isReceived, m3,cargoSupplierFk, kg,vTravelFk
|
||||
FROM travel
|
||||
WHERE id = vTravelFk;
|
||||
|
||||
SET vNewTravelFk = LAST_INSERT_ID();
|
||||
|
||||
SET vDone = FALSE;
|
||||
SET @isModeInventory = TRUE;
|
||||
|
||||
OPEN vRsEntry;
|
||||
|
||||
l: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vRsEntry INTO vAuxEntryFk;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE l;
|
||||
END IF;
|
||||
|
||||
CALL entry_cloneHeader(vAuxEntryFk, vNewEntryFk, vNewTravelFk);
|
||||
CALL entry_copyBuys(vAuxEntryFk, vNewEntryFk);
|
||||
|
||||
SELECT evaNotes INTO vEvaNotes
|
||||
FROM entry
|
||||
WHERE id = vAuxEntryFk;
|
||||
|
||||
UPDATE entry
|
||||
SET evaNotes = vEvaNotes
|
||||
WHERE id = vNewEntryFk;
|
||||
|
||||
END LOOP;
|
||||
|
||||
SET @isModeInventory = FALSE;
|
||||
CLOSE vRsEntry;
|
||||
|
||||
CALL util.tx_commit(vTx);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,15 @@
|
|||
DELIMITER $$
|
||||
$$
|
||||
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `util`.`tx_commit`(IN tx BOOL)
|
||||
BEGIN
|
||||
/**
|
||||
* Procedimiento para confirmar los cambios asociados a una transacción
|
||||
*
|
||||
* @param tx BOOL es true si existe transacción asociada
|
||||
*/
|
||||
IF tx THEN
|
||||
COMMIT;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,15 @@
|
|||
DELIMITER $$
|
||||
$$
|
||||
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `util`.`tx_rollback`(tx BOOL)
|
||||
BEGIN
|
||||
/**
|
||||
* Procedimiento para deshacer los cambios asociados a una transacción
|
||||
*
|
||||
* @param tx BOOL es true si existe transacción asociada
|
||||
*/
|
||||
IF tx THEN
|
||||
ROLLBACK;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `util`.`tx_start`(tx BOOL)
|
||||
BEGIN
|
||||
/**
|
||||
* Procedimiento para iniciar una transacción
|
||||
*
|
||||
* @param tx BOOL es true si existe transacción asociada
|
||||
*/
|
||||
IF tx THEN
|
||||
START TRANSACTION;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,6 +1,5 @@
|
|||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
const loggable = require('vn-loopback/util/log');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('cloneWithEntries', {
|
||||
|
@ -11,8 +10,9 @@ module.exports = Self => {
|
|||
type: 'number',
|
||||
required: true,
|
||||
description: 'The original travel id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
http: {source: 'path'},
|
||||
},
|
||||
],
|
||||
returns: {
|
||||
type: 'object',
|
||||
description: 'The new cloned travel id',
|
||||
|
@ -24,8 +24,20 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.cloneWithEntries = async(ctx, id) => {
|
||||
Self.cloneWithEntries = async(ctx, id, options) => {
|
||||
const conn = Self.dataSource.connector;
|
||||
const myOptions = {};
|
||||
let tx = options?.transaction;
|
||||
|
||||
try {
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
const travel = await Self.findById(id, {
|
||||
fields: [
|
||||
'id',
|
||||
|
@ -45,7 +57,6 @@ module.exports = Self => {
|
|||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`CALL travel_cloneWithEntries(?, ?, ?, ?, ?, ?, ?, @vTravelFk)`, [
|
||||
id,
|
||||
|
@ -61,7 +72,7 @@ module.exports = Self => {
|
|||
const newTravelIndex = stmts.push('SELECT @vTravelFk AS id') - 1;
|
||||
|
||||
const sql = ParameterizedSQL.join(stmts, ';');
|
||||
const result = await conn.executeStmt(sql);
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
const [lastInsert] = result[newTravelIndex];
|
||||
|
||||
if (!lastInsert.id)
|
||||
|
@ -77,8 +88,11 @@ module.exports = Self => {
|
|||
'agencyModeFk',
|
||||
'ref'
|
||||
]
|
||||
});
|
||||
|
||||
}, myOptions);
|
||||
return newTravel.id;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,66 +5,20 @@ describe('Travel cloneWithEntries()', () => {
|
|||
const travelId = 5;
|
||||
const currentUserId = 1102;
|
||||
const ctx = {req: {accessToken: {userId: currentUserId}}};
|
||||
let travelBefore;
|
||||
let newTravelId;
|
||||
|
||||
// afterAll(async() => {
|
||||
// try {
|
||||
// const entries = await models.Entry.find({
|
||||
// where: {
|
||||
// travelFk: newTravelId
|
||||
// }
|
||||
// });
|
||||
// const entriesId = entries.map(entry => entry.id);
|
||||
|
||||
// // Destroy all entries buys
|
||||
// await models.Buy.destroyAll({
|
||||
// where: {
|
||||
// entryFk: {inq: entriesId}
|
||||
// }
|
||||
// });
|
||||
|
||||
// // Destroy travel entries
|
||||
// await models.Entry.destroyAll({
|
||||
// where: {
|
||||
// travelFk: newTravelId
|
||||
// }
|
||||
// });
|
||||
|
||||
// // Destroy new travel
|
||||
// await models.Travel.destroyById(newTravelId);
|
||||
|
||||
// // Restore original travel shipped & landed
|
||||
// const travel = await models.Travel.findById(travelId);
|
||||
// await travel.updateAttributes({
|
||||
// shipped: travelBefore.shipped,
|
||||
// landed: travelBefore.landed
|
||||
// });
|
||||
// } catch (error) {
|
||||
// console.error(error);
|
||||
// }
|
||||
// });
|
||||
|
||||
it(`should clone the travel and the containing entries`, async() => {
|
||||
pending('#2687 - Cannot make a data rollback because of the triggers');
|
||||
const tx = await models.Travel.beginTransaction({
|
||||
});
|
||||
const warehouseThree = 3;
|
||||
const agencyModeOne = 1;
|
||||
const yesterday = Date.vnNew();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
|
||||
travelBefore = await models.Travel.findById(travelId);
|
||||
await travelBefore.updateAttributes({
|
||||
shipped: yesterday,
|
||||
landed: yesterday
|
||||
});
|
||||
|
||||
newTravelId = await models.Travel.cloneWithEntries(ctx, travelId);
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
newTravelId = await models.Travel.cloneWithEntries(ctx, travelId, options);
|
||||
const travelEntries = await models.Entry.find({
|
||||
where: {
|
||||
travelFk: newTravelId
|
||||
}
|
||||
});
|
||||
|
||||
}, options);
|
||||
const newTravel = await models.Travel.findById(travelId);
|
||||
|
||||
expect(newTravelId).not.toEqual(travelId);
|
||||
|
@ -73,5 +27,14 @@ describe('Travel cloneWithEntries()', () => {
|
|||
expect(newTravel.warehouseOutFk).toEqual(warehouseThree);
|
||||
expect(newTravel.agencyModeFk).toEqual(agencyModeOne);
|
||||
expect(travelEntries.length).toBeGreaterThan(0);
|
||||
|
||||
await tx.rollback();
|
||||
const travelRemoved = await models.Travel.findById(newTravelId, options);
|
||||
|
||||
expect(travelRemoved).toBeNull();
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue