problema con Insert duplicidad en numeracion de tickets.

14/08/2007 - 21:13 por Danilo Reinoso | Informe spam
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

Preguntas similare

Leer las respuestas

#1 Victor Koch
14/08/2007 - 22:03 | Informe spam
Hola Danilo,

¿ Y para que tenes dos campos para lo mismo ? , porque directamente no usas
el campo Transacción como Numero Trabajo y dejas que lo maneje la base de
datos.

Por lo que vi el campo Transacción es autonumerico. Si el contador lo
manejas de esa forma vas a seguir teniendo el mismo problema, la solución es
usar el campo Transacción como Numero Trabajo o tener una tabla para las
numeraciones y envolver la numeración de la tabla de numeraciones con la
inserción del movimiento en una transacción:

Comienzo transacción
Aumentar en uno la tabla de numeraciones
Tomar el nuevo numero generado de la tabla de numeraciones
Insertar el movimiento en la tabla de movimientos
Finalizar transacción


Un saludo, Víctor Koch.


"Danilo Reinoso" escribió en el mensaje
news:usWR$
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


Respuesta Responder a este mensaje
#2 Danilo Reinoso
14/08/2007 - 22:25 | Informe spam
Gracias Victor por responder

Te comento porque lo dos campos:
Esto es porque si una orden se mueve completa a otro departamento debe
mantener el mismo numero de trabajo.
Si te da cuenta en el Store Procedure InsertMovimiento primero se inserta la
transaccion y luego se resta la
[Cantidad Aceptada] > total pieza movidas puede ser igual o
menor, menor cuando es un parcial.
Si el Campo [Cantidad Aceptada]=0 se elimina el movimiento anterior y queda
el nuevo.

Lo que he hecho para corregir la duplicidad por el momento es cuando inserto
el movimiento verifico si la [Cantidad Aceptada]
Ticket anterior es diferente [Cantidad Aceptada] nuevo tickets, actualizo el
campo [Numero Trabajo]=CONVERT(VARCHAR(50),@New_TR)
del Nuevo Movimiento.
EJ: UPDATE Movimientos SET [Numero Trabajo]=CONVERT(VARCHAR(50),@NEW_TR)
WHERE [Cantidad Aceptada]<>(SELECT [Cantidad Aceptada] FROM Movimientos
WHERE Transaccion = @Transaccion)
AND Transaccion = @NEW_TR

Si existe otra solucion sigo quedando a tu disposicion para cualquier
informacion adicional.


"Victor Koch" <v i c t o r (arroba)correo(punto)waldbott(punto)com(punto)ar>
wrote in message news:%23%
Hola Danilo,

¿ Y para que tenes dos campos para lo mismo ? , porque directamente no
usas
el campo Transacción como Numero Trabajo y dejas que lo maneje la base de
datos.

Por lo que vi el campo Transacción es autonumerico. Si el contador lo
manejas de esa forma vas a seguir teniendo el mismo problema, la solución
es
usar el campo Transacción como Numero Trabajo o tener una tabla para las
numeraciones y envolver la numeración de la tabla de numeraciones con la
inserción del movimiento en una transacción:

Comienzo transacción
Aumentar en uno la tabla de numeraciones
Tomar el nuevo numero generado de la tabla de numeraciones
Insertar el movimiento en la tabla de movimientos
Finalizar transacción


Un saludo, Víctor Koch.


"Danilo Reinoso" escribió en el
mensaje
news:usWR$
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






email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida