#7919 delete if ticketRefund #3091

Merged
jorgep merged 9 commits from 7919-deleteTicketRefund into dev 2024-10-21 11:21:34 +00:00
14 changed files with 140 additions and 88 deletions
Showing only changes of commit 6f8a005726 - Show all commits

View File

@ -19,8 +19,15 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const [info, info2, [{'@vCollectionFk': collectionFk}]] = await Self.rawSql(
'CALL vn.collection_getAssigned(?, @vCollectionFk);SELECT @vCollectionFk', [userId], myOptions); const randStr = Math.random().toString(36).substring(3);
const result = await Self.rawSql(`
CALL vn.collection_getAssigned(?, @vCollectionFk);
SELECT @vCollectionFk ?
`, [userId, randStr], myOptions);
const collectionFk = result.find(item => item[0]?.[randStr] !== undefined)?.[0]?.[randStr];
if (!collectionFk) throw new UserError('There are not picking tickets'); if (!collectionFk) throw new UserError('There are not picking tickets');
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions); await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);

View File

@ -72,9 +72,9 @@ describe('Renew Token', () => {
} }
expect(error).toBeDefined(); expect(error).toBeDefined();
const query = 'SELECT * FROM util.debug';
const debugLog = await models.Application.rawSql(query, null); const query = 'SELECT * FROM util.debug WHERE variable = "renewToken"';
const debugLog = await models.Application.rawSql(query);
expect(debugLog.length).toEqual(1); expect(debugLog.length).toEqual(1);
}); });

View File

@ -5,100 +5,139 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`collection_getAssigne
) )
BEGIN BEGIN
/** /**
* Comprueba si existen colecciones libres que se ajustan al perfil del usuario * Comprueba si existen colecciones libres que se ajustan
* y le asigna la más antigua. * al perfil del usuario y le asigna la más antigua.
* Añade un registro al semillero de colecciones y hace la reserva para la colección * Añade un registro al semillero de colecciones.
* *
* @param vUserFk Id de usuario * @param vUserFk Id de usuario
* @param vCollectionFk Id de colección * @param vCollectionFk Id de colección
*/ */
DECLARE vHasTooMuchCollections BOOL; DECLARE vHasTooMuchCollections BOOL;
DECLARE vItemPackingTypeFk VARCHAR(1); DECLARE vDone BOOL DEFAULT FALSE;
DECLARE vWarehouseFk INT; DECLARE vCollectionWorker INT;
DECLARE vLockName VARCHAR(215); DECLARE vMaxNotAssignedCollectionLifeTime TIME;
DECLARE vLockTime INT DEFAULT 30;
DECLARE vCollections CURSOR FOR
WITH collections AS (
SELECT tc.collectionFk,
SUM(sv.volume) volume,
c.saleTotalCount,
c.itemPackingTypeFk,
c.trainFk,
c.warehouseFk,
c.wagons
FROM vn.ticketCollection tc
JOIN vn.collection c ON c.id = tc.collectionFk
JOIN vn.saleVolume sv ON sv.ticketFk = tc.ticketFk
WHERE c.workerFk IS NULL
AND sv.shipped >= util.VN_CURDATE()
GROUP BY tc.collectionFk
) SELECT c.collectionFk
FROM collections c
JOIN vn.operator o
WHERE o.workerFk = vUserFk
AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL)
AND (c.itemPackingTypeFk = o.itemPackingTypeFk OR o.itemPackingTypeFk IS NULL)
AND o.numberOfWagons = c.wagons
AND o.trainFk = c.trainFk
AND o.warehouseFk = c.warehouseFk;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
-- Si hay colecciones sin terminar, sale del proceso
DECLARE EXIT HANDLER FOR SQLEXCEPTION DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN BEGIN
IF vLockName IS NOT NULL THEN ROLLBACK;
DO RELEASE_LOCK(vLockName);
END IF;
RESIGNAL; RESIGNAL;
END; END;
-- Si hay colecciones sin terminar, sale del proceso
CALL collection_get(vUserFk); CALL collection_get(vUserFk);
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime
pc.collection_assign_lockname INTO vHasTooMuchCollections, vMaxNotAssignedCollectionLifeTime
INTO vHasTooMuchCollections, FROM productionConfig pc
vLockName LEFT JOIN tmp.collection ON TRUE;
FROM tmp.collection c
JOIN productionConfig pc;
DROP TEMPORARY TABLE tmp.collection; DROP TEMPORARY TABLE tmp.collection;
IF vHasTooMuchCollections THEN IF vHasTooMuchCollections THEN
CALL util.throw('There are pending collections'); CALL util.throw('Hay colecciones pendientes');
END IF;
SELECT warehouseFk, itemPackingTypeFk
INTO vWarehouseFk, vItemPackingTypeFk
FROM operator
WHERE workerFk = vUserFk;
SET vLockName = CONCAT_WS('/',
vLockName,
vWarehouseFk,
vItemPackingTypeFk
);
IF NOT GET_LOCK(vLockName, vLockTime) THEN
CALL util.throw(CONCAT('Cannot get lock: ', vLockName));
END IF; END IF;
-- Se eliminan las colecciones sin asignar que estan obsoletas -- Se eliminan las colecciones sin asignar que estan obsoletas
INSERT INTO ticketTracking(stateFk, ticketFk)
SELECT s.id, tc.ticketFk
FROM collection c
JOIN ticketCollection tc ON tc.collectionFk = c.id
JOIN state s ON s.code = 'PRINTED_AUTO'
JOIN productionConfig pc
WHERE c.workerFk IS NULL
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime;
DELETE c INSERT INTO ticketTracking(stateFk, ticketFk)
FROM collection c SELECT s.id, tc.ticketFk
JOIN productionConfig pc FROM `collection` c
WHERE c.workerFk IS NULL JOIN ticketCollection tc ON tc.collectionFk = c.id
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime; JOIN `state` s ON s.code = 'PRINTED_AUTO'
WHERE c.workerFk IS NULL
AND TIMEDIFF(util.VN_NOW(), c.created) > vMaxNotAssignedCollectionLifeTime;
DELETE FROM `collection`
WHERE workerFk IS NULL
AND TIMEDIFF(util.VN_NOW(), created) > vMaxNotAssignedCollectionLifeTime;
-- Se añade registro al semillero -- Se añade registro al semillero
INSERT INTO collectionHotbed
SET userFk = vUserFk; INSERT INTO collectionHotbed(userFk) VALUES(vUserFk);
-- Comprueba si hay colecciones disponibles que se ajustan a su configuracion -- Comprueba si hay colecciones disponibles que se ajustan a su configuracion
SELECT MIN(c.id) INTO vCollectionFk
FROM collection c OPEN vCollections;
JOIN operator o ON (o.itemPackingTypeFk = c.itemPackingTypeFk l: LOOP
OR c.itemPackingTypeFk IS NULL) SET vDone = FALSE;
AND o.numberOfWagons = c.wagons FETCH vCollections INTO vCollectionFk;
AND o.trainFk = c.trainFk
AND o.warehouseFk = c.warehouseFk IF vDone THEN
AND c.workerFk IS NULL LEAVE l;
WHERE o.workerFk = vUserFk; END IF;
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET vCollectionFk = NULL;
RESIGNAL;
END;
START TRANSACTION;
SELECT workerFk INTO vCollectionWorker
FROM `collection`
WHERE id = vCollectionFk FOR UPDATE;
IF vCollectionWorker IS NULL THEN
UPDATE `collection`
SET workerFk = vUserFk
WHERE id = vCollectionFk;
COMMIT;
LEAVE l;
END IF;
ROLLBACK;
END;
END LOOP;
CLOSE vCollections;
IF vCollectionFk IS NULL THEN IF vCollectionFk IS NULL THEN
CALL collection_new(vUserFk, vCollectionFk); CALL collection_new(vUserFk, vCollectionFk);
START TRANSACTION;
SELECT workerFk INTO vCollectionWorker
FROM `collection`
WHERE id = vCollectionFk FOR UPDATE;
IF vCollectionWorker IS NULL THEN
UPDATE `collection`
SET workerFk = vUserFk
WHERE id = vCollectionFk;
END IF;
COMMIT;
END IF; END IF;
UPDATE collection
SET workerFk = vUserFk
WHERE id = vCollectionFk;
CALL itemShelvingSale_addByCollection(vCollectionFk); CALL itemShelvingSale_addByCollection(vCollectionFk);
DO RELEASE_LOCK(vLockName);
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -1,3 +1,3 @@
ALTER TABLE vn.clientObservation ALTER TABLE vn.clientObservation DROP COLUMN IF EXISTS observationTypeFk;
ADD COLUMN observationTypeFk TINYINT(3) UNSIGNED NOT NULL, ALTER TABLE vn.clientObservation ADD COLUMN IF NOT EXISTS observationTypeFk TINYINT(3) UNSIGNED NULL;
ADD CONSTRAINT clientObservationTypeFk FOREIGN KEY (observationTypeFk) REFERENCES vn.observationType(id); ALTER TABLE vn.clientObservation ADD CONSTRAINT clientObservationTypeFk FOREIGN KEY IF NOT EXISTS (observationTypeFk) REFERENCES vn.observationType(id);

View File

@ -1,5 +1,3 @@
/*
UPDATE vn.sale UPDATE vn.sale
SET originalQuantity = quantity SET originalQuantity = quantity
WHERE originalQuantity IS NULL WHERE originalQuantity IS NULL
*/

View File

@ -1 +1 @@
-- ALTER TABLE vn.sale MODIFY COLUMN originalQuantity decimal(10,2) DEFAULT 0.00 NOT NULL COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity'; ALTER TABLE vn.sale MODIFY COLUMN originalQuantity decimal(10,2) DEFAULT 0.00 NOT NULL COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity';

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.sector ADD isOnReservationMode tinyint(1) DEFAULT FALSE NULL;

View File

@ -0,0 +1,3 @@
ALTER TABLE `vn`.`ticketConfig`
ADD COLUMN `closureDaysAgo` int(11) NOT NULL DEFAULT 2 COMMENT 'Number of days to look back for ticket closure',
ADD CONSTRAINT `closureDaysAgo_check` CHECK (`closureDaysAgo` > 0);

View File

@ -59,6 +59,9 @@
"isReserve": { "isReserve": {
"type": "boolean", "type": "boolean",
"required": true "required": true
},
"isOnReservationMode": {
"type": "boolean"
} }
} }
} }

View File

@ -53,8 +53,9 @@ module.exports = Self => {
JOIN province p ON p.id = c.provinceFk JOIN province p ON p.id = c.provinceFk
JOIN country co ON co.id = p.countryFk JOIN country co ON co.id = p.countryFk
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
JOIN ticketConfig tc ON TRUE
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered')) WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
AND DATE(t.shipped) BETWEEN ? - INTERVAL 7 DAY AND util.dayEnd(?) AND t.shipped BETWEEN ? - INTERVAL tc.closureDaysAgo DAY AND util.dayEnd(?)
AND t.refFk IS NULL AND t.refFk IS NULL
GROUP BY t.id GROUP BY t.id
`, [toDate, toDate]); `, [toDate, toDate]);
@ -108,6 +109,7 @@ module.exports = Self => {
JOIN alertLevel al ON al.id = ts.alertLevel JOIN alertLevel al ON al.id = ts.alertLevel
JOIN client c ON c.id = t.clientFk JOIN client c ON c.id = t.clientFk
JOIN province p ON p.id = c.provinceFk JOIN province p ON p.id = c.provinceFk
JOIN ticketConfig tc ON TRUE
LEFT JOIN autonomy a ON a.id = p.autonomyFk LEFT JOIN autonomy a ON a.id = p.autonomyFk
JOIN country co ON co.id = p.countryFk JOIN country co ON co.id = p.countryFk
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
@ -116,7 +118,7 @@ module.exports = Self => {
LEFT JOIN vn.invoiceOutSerial ios ON ios.taxAreaFk = 'WORLD' LEFT JOIN vn.invoiceOutSerial ios ON ios.taxAreaFk = 'WORLD'
AND ios.code = invoiceSerial(t.clientFk, t.companyFk, 'multiple') AND ios.code = invoiceSerial(t.clientFk, t.companyFk, 'multiple')
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered')) WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
AND DATE(t.shipped) BETWEEN ? - INTERVAL 2 DAY AND util.dayEnd(?) AND t.shipped BETWEEN ? - INTERVAL tc.closureDaysAgo DAY AND util.dayEnd(?)
AND t.refFk IS NULL AND t.refFk IS NULL
AND IFNULL(a.hasDailyInvoice, co.hasDailyInvoice) AND IFNULL(a.hasDailyInvoice, co.hasDailyInvoice)
GROUP BY ticketFk GROUP BY ticketFk
@ -141,9 +143,10 @@ module.exports = Self => {
JOIN alertLevel al ON al.id = ts.alertLevel JOIN alertLevel al ON al.id = ts.alertLevel
JOIN agencyMode am ON am.id = t.agencyModeFk JOIN agencyMode am ON am.id = t.agencyModeFk
JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
JOIN ticketConfig tc ON TRUE
LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id
SET t.routeFk = NULL SET t.routeFk = NULL
WHERE DATE(t.shipped) BETWEEN ? - INTERVAL 2 DAY AND util.dayEnd(?) WHERE t.shipped BETWEEN ? - INTERVAL tc.closureDaysAgo DAY AND util.dayEnd(?)
AND al.code NOT IN ('DELIVERED', 'PACKED') AND al.code NOT IN ('DELIVERED', 'PACKED')
AND NOT t.packages AND NOT t.packages
AND tob.id IS NULL AND tob.id IS NULL

View File

@ -12,10 +12,7 @@ module.exports = async function(ctx, Self, tickets, options) {
Object.assign(myOptions, options); Object.assign(myOptions, options);
let tx; let tx;
// if (!myOptions.transaction) { // IMPORTANT: Due to its high cost in production, wrapping this process in a transaction may cause timeouts.
// tx = await Self.beginTransaction({});
// myOptions.transaction = tx;
// }
if (tickets.length == 0) return; if (tickets.length == 0) return;

View File

@ -50,9 +50,9 @@ describe('Ticket closure functionality', () => {
expect(ticketStateBefore.code).not.toBe(ticketStateAfter.code); expect(ticketStateBefore.code).not.toBe(ticketStateAfter.code);
const ticketAfter = await models.TicketState.findById(ticketId, null, options); const ticketAfter = await models.Ticket.findById(ticketId, null, options);
expect(ticketAfter.refFk).toBeUndefined(); expect(ticketAfter.refFk).toBeNull();
}); });
it('should send Incoterms authorization email on first order', async() => { it('should send Incoterms authorization email on first order', async() => {

View File

@ -87,7 +87,7 @@ module.exports = Self => {
{ {
relation: 'sector', relation: 'sector',
scope: { scope: {
fields: ['warehouseFk', 'description'], fields: ['warehouseFk', 'description', 'isOnReservationMode'],
} }
}, { }, {
relation: 'printer', relation: 'printer',

View File

@ -1,6 +1,6 @@
{ {
"name": "salix-back", "name": "salix-back",
"version": "24.42.0", "version": "24.44.0",
"author": "Verdnatura Levante SL", "author": "Verdnatura Levante SL",
"description": "Salix backend", "description": "Salix backend",
"license": "GPL-3.0", "license": "GPL-3.0",