Saludos.
Ante todo Disculpen lo estenso de mi explicacion.
Utilizo SQL2000 Y MSAccess como from end
Estoy desarrollando un programa para el control de orden de manufactura.
El problema se da cuando tengo que generar un nuevo ticket o parcial de una
orden de trabajo.
El sistema permite que de una orden se pueda generar uno o varios parciales,
para lo cual utilizo la sigte rutina.
Deseo que el nuevo ticket el campo [Numero Trabajo] se numere a partir de la
ultima Transaccion+1 ver tabla movimiento.
Lo cual en alguno momento cuando dos usuarios estan generando algun parcial
el sistema le esta asignando el mismo
[Numero Trabajo] a dos movimientos diferentes.
Creo que aqui es donde esta el problema de concurrencia ver codigo mas
abajo:
rsTRMAX.Open "SELECT MAX(transaccion) AS trMAX FROM Movimientos", _
dbGoldControl, adOpenDynamic, adLockOptimistic
'adOpenForwardOnly, adLockReadOnly
trMAX = Nz(rsTRMAX!trMAX, 0)
rsTRMAX.Close
Set rsTRMAX = Nothing
Me.Numero_Trabajo = strTipo & CLng(trMAX + 1)
El sistema tiene dos tablas
Movimientos=Ordenes en procesos
Historial=Historial de movimientos de ordenes.
DDL:
if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[Movimientos]') and OBJECTPROPERTY(id, N'IsUserTable') =
1)
drop table [dbo].[Movimientos]
GO
CREATE TABLE [dbo].[Movimientos] (
[Transaccion] [int] IDENTITY (1, 1) NOT NULL ,
[Numero Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Movido Desde] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Movido Hasta] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Fecha Movimiento] [datetime] NULL ,
[Hora Movimiento] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Item No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Item Descripcion] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Cantidad Aceptada] [float] NULL ,
[Peso Aceptada] [float] NULL ,
[Cantidad Rechazada] [float] NULL ,
[Peso Rechazada] [float] NULL ,
[Cantidad Dañada] [float] NULL ,
[Peso Dañada] [float] NULL ,
[Peso Piedras] [float] NULL ,
[Peso Extra] [float] NULL ,
[Descripcion Extra] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT
NULL ,
[Peso Salida] [float] NULL ,
[Total Orden] [float] NULL ,
[Total Peso] [float] NULL ,
[Direccion Foto] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Ultimo_Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Empleado No] [int] NULL ,
[Empleado Nombre] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Operacion No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas_Mov] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Declarado] [bit] NULL ,
[Duracion] [float] NULL ,
[Usuario Sistema] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Status] [int] NULL
) ON [PRIMARY]
GO
CREATE INDEX [IndicePorNumeroTrabajo] ON [dbo].[Movimientos]([Numero
Trabajo]) ON [PRIMARY]
GO
CREATE INDEX [IndicePorMovidoDesde] ON [dbo].[Movimientos]([Movido Desde])
ON [PRIMARY]
GO
CREATE INDEX [IndicePorMovidoHasta] ON [dbo].[Movimientos]([Movido Hasta])
ON [PRIMARY]
GO
CREATE INDEX [IndicePorFechaMovimiento] ON [dbo].[Movimientos]([Fecha
Movimiento]) ON [PRIMARY]
GO
CREATE INDEX [IndicePorEmpleadoNo] ON [dbo].[Movimientos]([Empleado No])
ON [PRIMARY]
GO
CREATE UNIQUE INDEX [IndicePorTransaccion] ON
[dbo].[Movimientos]([Transaccion]) ON [PRIMARY]
GO
CREATE INDEX [IndicePorStatus] ON [dbo].[Movimientos]([Status]) ON
[PRIMARY]
GO
CREATE INDEX [IX_Movimientos] ON [dbo].[Movimientos]([Item No]) ON
[PRIMARY]
GO
CREATE INDEX [IndicePorOperacionNo] ON [dbo].[Movimientos]([Operacion No])
ON [PRIMARY]
GO
CREATE INDEX [Indice_Ultimo_Trabajo] ON
[dbo].[Movimientos]([Ultimo_Trabajo]) ON [PRIMARY]
GO
CREATE INDEX [IX_Descripcion_Extra] ON [dbo].[Movimientos]([Descripcion
Extra]) ON [PRIMARY]
GO
**** Rutina de Access que inserta el movimiento e invoca el store procedure
de SQL (InsertMovimiento)
'Insert datos del Movimiento
Dim rsTRMAX As New ADODB.Recordset
Dim trMAX As Long
dbGoldControl.BeginTrans
rsTRMAX.Open "SELECT MAX(transaccion) AS trMAX FROM Movimientos", _
dbGoldControl, adOpenDynamic, adLockOptimistic
'adOpenForwardOnly, adLockReadOnly
trMAX = Nz(rsTRMAX!trMAX, 0)
rsTRMAX.Close
Set rsTRMAX = Nothing
Me.Numero_Trabajo = strTipo & CLng(trMAX + 1)
With ocmd
.ActiveConnection = dbGoldControl
.CommandType = adCmdStoredProc
.CommandText = "InsertMovimiento"
.Parameters.Append .CreateParameter("@Numero_Trabajo", adVarChar,
adParamInput, 50, Me.Numero_Trabajo)
.Parameters.Append .CreateParameter("@Movido_Desde", adVarChar,
adParamInput, 50, Me.Movido_Desde)
.Parameters.Append .CreateParameter("@Movido_Hasta", adVarChar,
adParamInput, 50, Me.Movido_Hasta)
.Parameters.Append .CreateParameter("@Item_No", adVarChar,
adParamInput, 50, Me.Item_No)
.Parameters.Append .CreateParameter("@Item_Descripcion", adVarChar,
adParamInput, 50, Me.Item_Descripcion)
.Parameters.Append .CreateParameter("@Cantidad_Aceptada", adDouble,
adParamInput, , CDbl(Me.Cantidad_Aceptada))
.Parameters.Append .CreateParameter("@Peso_Aceptada", adDouble,
adParamInput, , CDbl(Me.PesoReal1))
.Parameters.Append .CreateParameter("@Cantidad_Rechazada", adDouble,
adParamInput, , CDbl(Me.Cantidad_Rechazada))
.Parameters.Append .CreateParameter("@Peso_Rechazada", adDouble,
adParamInput, , CDbl(Me.PesoReal2))
.Parameters.Append .CreateParameter("@Cantidad_Danada", adDouble,
adParamInput, , CDbl(Me.Cantidad_Dañada))
.Parameters.Append .CreateParameter("@Peso_Danada", adDouble,
adParamInput, , CDbl(Me.PesoReal3))
.Parameters.Append .CreateParameter("@Peso_Piedras", adDouble,
adParamInput, , CDbl(Me.PesoReal4))
.Parameters.Append .CreateParameter("@Peso_Extra", adDouble,
adParamInput, , CDbl(Me.Peso_Extra))
.Parameters.Append .CreateParameter("@Descripcion_Extra", adVarChar,
adParamInput, 50, Me.Descripcion_Extra)
.Parameters.Append .CreateParameter("@Peso_Salida", adDouble,
adParamInput, , CDbl(Me.Peso_Salida))
.Parameters.Append .CreateParameter("@Direccion_Foto", adVarChar,
adParamInput, 50, Me.Direccion_Foto)
.Parameters.Append .CreateParameter("@Empleado_No", adInteger,
adParamInput, 4, Me.Empleado_No)
.Parameters.Append .CreateParameter("@Empleado_Nombre", adVarChar,
adParamInput, 50, Me.Empleado_Nombre)
.Parameters.Append .CreateParameter("@Operacion_No", adVarChar,
adParamInput, 50, Nz(Me.Operacion_No, ""))
.Parameters.Append .CreateParameter("@Duracion", adDouble,
adParamInput, , CDbl(Me.Duracion))
.Parameters.Append .CreateParameter("@Total_Orden", adDouble,
adParamInput, , CDbl(Me.Total_Orden))
.Parameters.Append .CreateParameter("@Total_Peso", adDouble,
adParamInput, , CDbl(Me.Total_Peso))
.Parameters.Append .CreateParameter("@Notas", adVarChar,
adParamInput, 100, Me.Notas)
.Parameters.Append .CreateParameter("@Notas_Mov", adVarChar,
adParamInput, 100, Me.Notas_Mov)
.Parameters.Append .CreateParameter("@Ultimo_Trabajo", adVarChar,
adParamInput, 50, Me.Ultimo_Trabajo)
.Parameters.Append .CreateParameter("@TotalPiezas", adDouble,
adParamInput, , TotalPiezas)
.Parameters.Append .CreateParameter("@TotalPesos", adDouble,
adParamInput, , TotalPesos)
.Parameters.Append .CreateParameter("@Transaccion", adInteger,
adParamInput, , Me.Transaccion)
.Parameters.Append .CreateParameter("@New_TR", adInteger,
adParamOutput)
.Execute , , adExecuteNoRecords
End With
Me.NewTR = ocmd.Parameters("@New_TR")
Set ocmd = Nothing
dbGoldControl.CommitTrans
************* Store Procedure ****************
CREATE PROCEDURE InsertMovimiento
@Numero_Trabajo VARCHAR(50),
@Movido_Desde VARCHAR(50),
@Movido_Hasta VARCHAR(50),
@Item_No VARCHAR(50),
@Item_Descripcion VARCHAR(50),
@Cantidad_Aceptada DECIMAL(10,2),
@Peso_Aceptada DECIMAL(10,2),
@Cantidad_Rechazada DECIMAL(10,2),
@Peso_Rechazada DECIMAL(10,2),
@Cantidad_Danada DECIMAL(10,2),
@Peso_Danada DECIMAL(10,2),
@Peso_Piedras DECIMAL(10,2),
@Peso_Extra DECIMAL(10,2),
@Descripcion_Extra VARCHAR(50),
@Peso_Salida DECIMAL(10,2),
@Direccion_Foto VARCHAR(50),
@Empleado_No INT,
@Empleado_Nombre VARCHAR(50),
@Operacion_No VARCHAR(50),
@Duracion DECIMAL(10,2),
@Total_Orden DECIMAL(10,2),
@Total_Peso DECIMAL(10,2),
@Notas VARCHAR(100),
@Notas_Mov VARCHAR(100),
@Ultimo_Trabajo VARCHAR(50),
@TotalPiezas DECIMAL(10,2),
@TotalPesos DECIMAL(10,2),
@Transaccion INT,
@NEW_TR INT OUTPUT
AS
SET NOCOUNT ON
INSERT INTO Movimientos([Numero Trabajo],
[Movido Desde],
[Movido Hasta],
[Item No],
[Item Descripcion],
[Cantidad Aceptada],
[Peso Aceptada],
[Cantidad Rechazada],
[Peso Rechazada],
[Cantidad Dañada],
[Peso Dañada], [Peso Piedras],
[Peso Extra],
[Descripcion Extra],
[Peso Salida],
[Direccion Foto],
[Empleado No],
[Empleado Nombre],
[Operacion No],
Duracion,
[Total Orden],
[Total Peso],
Notas,
Notas_Mov,
Ultimo_Trabajo)
VALUES(@Numero_Trabajo,
@Movido_Desde ,
@Movido_Hasta,
@Item_No,
@Item_Descripcion,
@Cantidad_Aceptada,
@Peso_Aceptada,
@Cantidad_Rechazada,
@Peso_Rechazada,
@Cantidad_Danada,
@Peso_Danada,
@Peso_Piedras,
@Peso_Extra,
@Descripcion_Extra,
@Peso_Salida,
@Direccion_Foto,
@Empleado_No,
@Empleado_Nombre,
@Operacion_No,
@Duracion,
@Total_Orden,
@Total_Peso,
@Notas,
@Notas_Mov,
@Ultimo_Trabajo)
SET @NEW_TR = SCOPE_IDENTITY()
UPDATE Movimientos SET [Cantidad Aceptada] = [Cantidad Aceptada] -
@TotalPiezas,
[Peso Aceptada] = [Peso Aceptada] - @TotalPesos,
[Peso Piedras] = [Peso Piedras] - @Peso_Piedras,
[Peso Extra] = @Peso_Extra,
[Peso Salida] = [Peso Aceptada] - @TotalPesos,
Status=1
WHERE Transaccion = @Transaccion
INSERT INTO Historial SELECT * FROM Movimientos M WHERE M.Transaccion =
@NEW_TR
DELETE FROM Movimientos WHERE Transaccion = @Transaccion AND [Cantidad
Aceptada]=0
SET NOCOUNT OFF
GO
Leer las respuestas