No permitir repetición de un servicio dependiendo de la fecha y usuario

Bueno cuento con el siguiente formulario que esta enfocado en la carga de servicio a un restaurante el cual carga los registros por medio del dni insertado por pistola de código de barras. La cual carga los servicios de Desayuno, Almuerzo, Cena y Colación. Todos estos se van asociando automáticamente a un campo bolean correspondiente dependiendo de la hora que sea, excepto colación que se activa por intervención del usuario ya que es variable.

Bueno quiero lograr lo siguiente :

Que no se pueda repetir un mismo servicio 2 veces en un mismo día para el mismo usuario.

Por ejemplo:

Si Dni "5" con fecha "24/10/2019" y servicio "desayuno" esta solo una vez en la tabla seria ok pero si no que arroje un cuadro de mensaje en el evento antes de insertar del formulario que no esta permitida esta acción, todo esto con el fin de que una persona no se repita un servicio.

Bueno y esto aplicarlo a todos los servicios que están en esta tabla los cuales son desayuno, almuerzo, cena y colación.

1 respuesta

Respuesta
1

Puedes comprobar si ya está de alta ese servicio con este código (para el desayuno, para los otros servicios solo has de cambiar el servicio):

If DCount("*","AsignarServicios","Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'")>0 Then

luego las lineas que sigan al Then dependerán de en qué evento lo pongas, algo que no tengo claro al no saber cómo funciona tu formulario.

Por ejemplo, si lo pones en algún evento "después de", podrías lanzar un mensaje y deshacer los cambios:

If DCount("*","AsignarServicios","Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'")>0 Then
  Msgbox "El usuario ya usó ese servicio en el día seleccionado"
  Me.Undo
End If

Si lo pones en un evento "antes de", podrías lanzar un mensaje y cancelar el evento:

If DCount("*","AsignarServicios","Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'")>0 Then
  Msgbox "El usuario ya usó ese servicio en el día seleccionado"
  Cancel=True
End If

Un saludo.


Hola gracias por tu respuesta, pero algo debo estar haciendo mal que no esta funcionando correctamente y he probado las dos opciones que me has dado.

Con la primera opción en el evento antes de insertar

Private Sub Form_AfterInsert()
If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó ese servicio en el día seleccionado"
  Me.Undo
End If
End Sub

sucede que al momento de insertar el nuevo dni arroja de inmediatamente el mensaje "El usuario ya usó ese servicio en el día seleccionado" siendo que lo estoy probando con la tabla sin ningún registro, quizás lo que sucede es que considera el mismo registro que se esta insertando en el momento y de allí que pasa esto.

muestro captura

lo segundo que pasa con este código es que después de actualizar la tabla el registro si se lleva a cavo y no debería ser así, ya que, tu mencionaste : si lo pones en algún evento "después de", podrías lanzar un mensaje y deshacer los cambios

Hora con el segundo método que lo he puesto en el evento antes de insertar

Private Sub Form_BeforeInsert(Cancel As Integer)
If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó ese servicio en el día seleccionado"
  Cancel = True
End If
End Sub

Sucede que me arroja un error de inmediato adjunto captura

 Bueno esto es lo que me sucede en y lo otro es que me gustaría que el código revisara cada servicio simultáneamente.


                    

Perdón la primera opción es después de insertar

Primero: el código funciona perfectamente, el problema está en que lo has puesto en los eventos equivocados...

El evento "Después de Insertar" del formulario se produce una vez que ya se han guardado los datos, por tanto, la validación siempre va a ser cierta porque el registro recién añadido cumple esa condición. Además, como los datos ya se han guardado, no hay nada que deshacer.

El evento "Antes de insertar" del formulario se ejecuta al escribir el primer carácter en un control de un nuevo registro, luego es lógico que te salte un error, porque haces una validación sin sentido.

Lo más sensato hubiera sido que usases los eventos "Después de actualizar" o "Antes de actualizar" del formulario, aunque si usas el primero vas a tener el mismo problema que te comentaba antes para "después de insertar", como ya has actualizado el registro, ya no tienes nada que deshacer.

Segundo: yo no te puedo indicar en qué evento lo has de colocar, porque no sé cómo funciona tu formulario... Si tienes casillas de verificación para marcar los servicios, el código te funcionará perfectamente en los eventos "antes de actualizar" o "después de actualizar" de cada casilla (si lo pones en el evento después, Me. Undo deshará el registro, Me. NombreCasilla. Undo deshará solo el cambio en la casilla). Si tienes botones para ejecutar una SQL de actualización (o inserción), puedes hacer la verificación en el código del propio botón y ejecutar la SQL o lanzar el mensaje según corresponda.

Te dejo un archivo con algunas opciones: http://www.filebig.net/files/SjwvWWt7fz 

Muchas gracias, pero no se como hacer para que revise todos los servicios simultáneamente osea desayuno, almuerzo, cena y colación.

me ayudarías por favor

No sé a qué te refieres por "simultáneamente"...

¿Qué los tenga todos marcados? :

If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then

¿o que mire uno a uno pero para los cuatro checks ?:

If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de desayuno en el día seleccionado"
  ...
End If
If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado"
  ...
End If
If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado"
  ...
End If
If DCount("*", "AsignarServicios", "Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado"
  ...
End If

que mire uno a uno pero para los cuatro checks. Trate de poner ese código, pero no me resulta  ,ya que, cambie  la hora para que cargara otro servicio y me arroja el mensaje "El usuario ya usó el servicio de Almuerzo en el día seleccionado"

Private Sub Form_BeforeUpdate(Cancel As Integer)
If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de desayuno en el día seleccionado"
  Cancel = True
End If
If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado"
  Cancel = True
End If
If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado"
  Cancel = True
End If
If DCount("*", "AsignarServicios", "Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
  MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado"
  Cancel = True
End If
End Sub

y bueno con respecto al formulario los únicos campos que manipula el usuario es dni (que se inserta con la pistola de codigo de barras) y el bolean de "colación" que se ve en la imagen que se utiliza cuando el usuario no quiere almuerzo y en cambio pide una colación.

Para que se ingresen los servicios utilizo el siguiente codigo.

Private Sub DNI_AfterUpdate()
If Colacion = False Then
If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
Desayuno = True
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then
Almuerzo = True
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then
Cena = True
End If
End If
End Sub

el cual funciona perfecto.

no se que hacer 

Si hubieras empezado por ahí (por cómo funciona tu formulario) hubiéramos llegado a una solución mucho antes...

Haz esto, en el código que ya tienes:

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then  Desayuno = True
  End IF
ElseIf ...

Y así con los otros dos servicios.

quedaría así??

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True
End If
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Aluerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True
End If
End Sub

Disculpa, que copie el If que no era...

Quedaría así:

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then  Desayuno = True
  End IF
ElseIf ...

Y tendrías que cambiar Desayuno por Cena y Almuerzo en los ElseIfs correspondientes

lo ingresa de igual forma , pero sin check cuando se repite el servicio en cambio la colación permite el duplicado y con check cuando se ingresan

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True
    ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then
      If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True
    ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then
      If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True
End If
End If
End Sub

ademas le quitaste el mensaje y que no lo ingrese si ya estaba en la tabla.

lo probé así también pero no funciono 

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True
     MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado"
     Cancel = True
    ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then
      If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True
      MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado"
      Cancel = True
    ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then
      If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True
      MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado"
      Cancel = True
End If
End If
End Sub

me estoy volviendo loco!!

Sin mensaje:

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
      If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then 
          Desayuno = True
      Else
          Me.Undo
      End If
    ElseIf 

Con mensaje:

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
     If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then 
        Desayuno = True
     Else 
        Msgbox "..."
        Me.Undo
     End If
ElseIf

Lo que no puedes pretender es que copiando lo que te de la gana de las diferentes soluciones que te propongo te funcione (El Cancel=True es para eventos "antes de", no "despues de"...)

Hola amigo muchas gracias eres el mejor y. me quedo así el código.

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
     If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then
        Desayuno = True
     Else
        MsgBox "El usuario ya usó el servicio de Desayuno en el día seleccionado"
        Me.Undo
     End If
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then
     If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then
        Almuerzo = True
     Else
        MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado"
        Me.Undo
     End If
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then
     If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then
        Cena = True
     Else
        MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado"
        Me.Undo
     End If
End If
End If
End Sub

 Pero sabes aun pasa por alto las colaciones y no podría utilizar el esa misma linea de código porque como dije en un comienzo la colación es variable , no tiene horario y de hecho no la tengo en la tabla de horarios de donde se toma la información para comparar que servicio se esta ingresando dependiendo de la hora.

muestro captura.

Hora esta comprobación seria diferente, ya que , colación puede reemplazar a los tres servicios (Desayuno, Almuerzo y Cena) por lo tanto debería ser algo así según lo que yo pienso:

si "DNI" dentro de la "fecha" tiene un total de tres servicios (desayuno, almuerzo y cena) entonces :

"El usuario no puede solicitar colaciones, ya que, adquirió todos los servicios de hoy"

de lo contrario si podría tomar el servicio. y el registro se carga en la tabla.

De ante mano de nuevo muchas gracias por tu valioso tiempo.

Todo el código que has puesto lo haces bajo la condición de que colación sea Falso, y nada más. Para contemplar la posibilidad de que colación sea verdadero, has de añadir, antes del último End If, un Else y ahí programar las validaciones que quieras si se marca la casilla Colacion.

En cuanto al código, viendo cómo son los códigos de validación anteriores, tendrías (con poco esfuerzo por tu parte) que ser capaz de hacerlo solo ( si no lo intentas, nunca aprenderás). Además, ya tienes una pista en los códigos que te he pasado en respuestas anteriores.

¡Gracias!  amigo lo intentare a ver que sucede y muchas gracias

Hola, perdón por lo majadero pero no se que paso y ahora no funciona que impida registros duplicados, si asigna correctamente los servicios.

http://www.filebig.net/files/KT54mZ55nA 

Te envío el archivo si me puedes ayudar ya que no consigo nada

Revisa los nombres de los campos en el código, porque hay uno que lo tienes mal...

no logro pillar la diferencia

Pues está bien claro, si en la tabla el campo se llama IdDni, en el código le tienes que llamar igual, no DNI (lo que te pongo en negrita) :

.... & "# AND IdDNI='" & Me.DNI & "'") = 0 Then

El Me. DNI que te pongo en cursiva, será el nombre que le tengas al cuadro de texto en el formulario, que no tiene por qué coincidir con el de la tabla. (Ahora no tengo acceso al archivo, pero lo compruebas tú)

Lo hice tal cual me dijiste pero no funciona además el campo en la tabLa si se llama DNI

Te explico el campo idni lo utilizo en el formulario para cargar la información con la pistola o manualmente, por lo tango debo tomar la información para comparar desde el dni que es un campo calculado que me extrae el dni ya con el formato que se utiliza.

Por lo mismo así debería esta bien, pero no

Private Sub DNI_AfterUpdate()
If Colacion = False Then
  If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then
     If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then
        Desayuno = True
     Else
        MsgBox "El usuario ya usó el servicio de Desayuno en el día seleccionado"
        Me.Undo
     End If
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then
     If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then
        Almuerzo = True
     Else
        MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado"
        Me.Undo
     End If
ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then
     If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then
        Cena = True
     Else
        MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado"
        Me.Undo
     End If
End If
End If
End Sub

Ayuda por favor!!

Vale, el campo en la tabla sí se llama DNI, pero el cuadro de texto del formulario no (se llama idDNI), y en eso no me hiciste caso.

También es buena costumbre usar formatos americanos de fecha, para que al usarla en código no se "confunda".

Dicho esto, si lo pones así:

.... AND Fecha=#" & Format(Me.Fecha, "mm/dd/yyyy") & "# AND DNI='" & Me.idDNI & "'")=0 ...

A mi me funciona.

¡Gracias!  ahora si funciona perfecto pero le hecho unos cambios ya que como te lo explicaba no puede comparar directamente del campo que esta en el tabla (DNI)con el campo del formulario(IdDNI) ,por que el dni se puede  ingresar de dos formas una manual que es escribir directamente el dni Ejemplo:15813443-8

como te lo muestro en la imagen

Y la otra forma es con la pistola que envía la información con otro formato a este campo (IdDNI) del formulario por lo mismo la comparación de los mismo no resultaría. 

Por lo tanto lo que hice fue agregar el campo que le daba el formato correcto al formulario y que el código comparece esos dos . Osea Campo dni de la tabla vs campo dni del formulario.

En fin funciona perfecto y el único cambio que realice fue el código que me has dado de la fecha , que al parecer eso era la causa , ya que había intentado esto mismo que hice ahora con el código antiguo y nada y ahora perfecto.

Ya lo probé con los distintos horarios y corre muy bien .

La verdad que muy agradecido con tu enorme paciencia y si se pudieran botar mas puntos claro que lo haría..

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas