
store procedure - descarga de stock
Publicado por Eduardo (5 intervenciones) el 14/10/2021 19:03:39
Saludos colegas,
Tengo la siguiente store procedure:
Lo que hace es descargar stock de un producto específico en la tabla ARTICULOS_STOCKS y agregar el movimiento en la tabla KARDEX. Para resolver la concurrencia se me ocurrió crear un campo en la tabla de productos llamado ARTICULO_LOCK, cuando se trata de mover stock de ese producto, la SP revisa que ARTICULO_LOCK sea igual a cero, si es cero lo pone en 1 y procede a realizar la descarga del stock y al terminar pone el ARTICULO_LOCK otra vez en cero.
Tengo 2 dudas al respecto (pero OJO, actualmente la store procedure esta funcionando):
1. ¿ Es esta la manera más optima de resolver la concurrencia ?
2. ¿ El número de intentos (5000) del bucle es el adecuado ?
Quisiera saber, desde su experiencia, como resuelven o han resuelto Ustedes este tema.
Cordiales saludos y gracias anticipadas por su tiempo.
Tengo la siguiente store procedure:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
CREATE PROCEDURE `sp_descargalotecualquiera` (IN localid INT,IN itemid INT,IN articuloid INT,IN cuantas INT,IN modulo CHAR(4),IN operacion INT)
BEGIN
DECLARE loteslista varchar(300) DEFAULT "" ;
DECLARE descargas int DEFAULT 0 ;
DECLARE descargar int DEFAULT cuantas ;
DECLARE intentos int DEFAULT 0 ;
DECLARE rlocked int DEFAULT 0 ;
DECLARE finished int DEFAULT 0 ;
DECLARE lote_id char(20) ;
DECLARE lote_vc char(8) ;
DECLARE lote_un int ;
DECLARE arti_fr int ;
DECLARE arti_cs numeric(12,2) ;
DECLARE arti_lk tinyint ;
DECLARE arti_st int ;
DECLARE curLotes CURSOR FOR
SELECT stock_lote,stock_vence,stock_unids
FROM articulos_stocks
WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_unids > 0
ORDER BY stock_vence ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1 ;
lock_arti: loop
select articulo_fracciones,articulo_costo_promed,articulo_rlock INTO arti_fr,arti_cs,arti_lk
from articulos
where articulo_id = articuloid ;
if arti_lk = 0 then
update articulos set articulo_rlock = 1 where articulo_id = articuloid ;
set rlocked = 1 ;
leave lock_arti ;
end if ;
set intentos = intentos + 1 ;
if intentos > 5000 then
leave lock_arti ;
end if ;
end loop lock_arti ;
if rlocked = 1 then
OPEN curLotes ;
getLotes: LOOP
SELECT COALESCE(sum(stock_unids),0) as stock_total INTO arti_st
FROM articulos_stocks
WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_unids > 0 ;
FETCH curLotes INTO lote_id,lote_vc,lote_un ;
IF finished = 1 THEN
LEAVE getLotes ;
END IF;
IF lote_un >= descargar THEN
UPDATE articulos_stocks SET stock_unids = stock_unids - descargar WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_lote = lote_id ;
INSERT INTO kardex (kdx_local_id,kdx_arti_id,kdx_fecha,kdx_tipo,kdx_oper_mod,kdx_oper_id,kdx_arti_frac,kdx_stock_ant,kdx_stock_mov,kdx_stock_sld ,kdx_costo_prm,kdx_lote,kdx_vence)
VALUES( localid ,articuloid ,NOW() ,"-" ,modulo ,operacion ,arti_fr ,arti_st ,descargar ,arti_st-descargar,arti_cs ,lote_id ,lote_vc ) ;
SET descargas = descargas + descargar ;
SET loteslista = CONCAT( loteslista,"(",lote_id,",",lote_vc,",",descargar,")" );
ELSE
UPDATE articulos_stocks SET stock_unids = 0 WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_lote = lote_id ;
INSERT INTO kardex (kdx_local_id,kdx_arti_id,kdx_fecha,kdx_tipo,kdx_oper_mod,kdx_oper_id,kdx_arti_frac,kdx_stock_ant,kdx_stock_mov,kdx_stock_sld ,kdx_costo_prm,kdx_lote,kdx_vence)
VALUES( localid ,articuloid ,NOW() ,"-" ,modulo ,operacion ,arti_fr ,arti_st ,lote_un ,arti_st-lote_un ,arti_cs ,lote_id ,lote_vc ) ;
SET descargas = descargas + lote_un ;
SET loteslista = CONCAT( loteslista,"(",lote_id,",",lote_vc,",",lote_un,")" );
END IF ;
IF descargas = cuantas THEN
LEAVE getLotes ;
ELSE
SET descargar = descargar - descargas ;
END IF ;
END LOOP getLotes ;
CLOSE curLotes ;
end if ;
insert into descargas values(modulo,operacion,itemid,loteslista) ;
update articulos set articulo_rlock = 0 where articulo_id = articuloid ;
END
Lo que hace es descargar stock de un producto específico en la tabla ARTICULOS_STOCKS y agregar el movimiento en la tabla KARDEX. Para resolver la concurrencia se me ocurrió crear un campo en la tabla de productos llamado ARTICULO_LOCK, cuando se trata de mover stock de ese producto, la SP revisa que ARTICULO_LOCK sea igual a cero, si es cero lo pone en 1 y procede a realizar la descarga del stock y al terminar pone el ARTICULO_LOCK otra vez en cero.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lock_arti: loop
select articulo_fracciones,articulo_costo_promed,articulo_rlock INTO arti_fr,arti_cs,arti_lk
from articulos
where articulo_id = articuloid ;
if arti_lk = 0 then
update articulos set articulo_rlock = 1 where articulo_id = articuloid ;
set rlocked = 1 ;
leave lock_arti ;
end if ;
set intentos = intentos + 1 ;
if intentos > 5000 then
leave lock_arti ;
end if ;
end loop lock_arti ;
Tengo 2 dudas al respecto (pero OJO, actualmente la store procedure esta funcionando):
1. ¿ Es esta la manera más optima de resolver la concurrencia ?
2. ¿ El número de intentos (5000) del bucle es el adecuado ?
Quisiera saber, desde su experiencia, como resuelven o han resuelto Ustedes este tema.
Cordiales saludos y gracias anticipadas por su tiempo.
Valora esta pregunta


0