Get Sequence ID based on last inserted

1

I have a problem that is giving me problems.

I have the following code:

$sql = $pdo->prepare ("SELECT cpf,idUser FROM 'tblContacts' where cpf = '".$cpf."' limit 1");
$sql->execute();
$row = $sql->fetch();

if($row != null)
  {
    //  echo "SQL 01 ". $sql;
    $randomicId = $row->idUser;
  } 
  else
  {
    switch ($horaAtual) {
      case ($horaAtual > $hora1 && $horaAtual < $hora2): $periodo = 'manha'; break;
      case ($horaAtual > $hora2 && $horaAtual < $hora3): $periodo = 'tarde'; break;
      default: $periodo =  'manha';
    }

    $sql2 = "SELECT * FROM 'tblUser' where grupo = 'vendas' and ativo = 1 and periodo = '".$periodo."' ORDER BY RAND() LIMIT 1";
    $stmt = $pdo->query($sql2); 
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if($row['idUser'] != null)
    {
      //echo "SQL 02 ". $sql2;
      $randomicId = $row['idUser'];
    }
  }

The code has 2 parts:

When a customer makes a registration, I take a user's ID and assign it to this user:

id   nome_cliente  ......  idUsuario

1    fulano                   2

If the customer does something else in the future, the system checks to see if there is an equal register in the database, if it has the same user ID.

If you do not have any records in the database, the system goes through a check process to get the ID of some users:

The system takes the current time:

  • If it is before 3:00 PM, it will query the database and select users in the morning.

  • If it is after 3pm, it will query the database and select the users in the afternoon.

Users table:

id   nome      periodo  ...
1    siclano    tarde

The system, after checking the period, takes a random ID with RAND() limit 1 .

So, the code is working.

But, taking the random ID, the following problem is happening: there are even more registrations for 1 user than for another.

So, I wanted, instead of randomly picking up, to assign an ID in sequence.

Checks the time, inserts the ID in sequence (obs: IDs vary).

IdUsuario : 2,34,45 

cadastro 1  - idUsuario : 2
cadastro 2  - idUsuario : 34
cadastro 3  - idUsuario : 45
cadastro 4  - idUsuario : 2
....

Can anyone help doing this?

    
asked by anonymous 08.07.2015 / 17:28

1 answer

1

To make this control you need to have a field where you control which was the last user used. I suggest doing a normalization in your bank, changing the field periodo passing the data to a table and storing only the ID of those records in the user table, and store in that table which was the last user used, so you will have a queue for each shift . Here's an example.

Basic modeling:

Shifts

CREATE TABLE 'turnos'(
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  nome VARCHAR(45),
  lastfunc INT
);

INSERT INTO turnos (nome) VALUES ('manhã'), ('tarde');

 _________________________
| id | nome  | lastfunc   |
|____|_______|____________|
| 1  | manhã |            |
|____|_______|____________|
| 2  | tarde |            |
|____|_______|____________|
2 registros

The lastfunc column will be used to control the user / employee sequence.

Employees

CREATE TABLE 'funcionarios'(
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  nome VARCHAR(45),
  turno_id INT NOT NULL,
  FOREIGN KEY (turno_id) REFERENCES turnos(id)
);

INSERT INTO funcionarios (nome, turno_id)  VALUES
('João', 1), ('Maria', 1), ('José', 2), ('Joana', 2);

 __________________________
| id | nome     | turno_id |
|____|__________|__________|
| 1  | João     | 1        |  ---
|____|__________|__________|    |-- Turno da Manhã
| 2  | Maria    | 1        |  ---
|____|__________|__________|
| 3  | José     | 2        |  ---
|____|__________|__________|    |-- Turno da Tarde
| 4  | Joana    | 2        |  ---
|____|__________|__________|
4 registros

Customers

CREATE TABLE 'clientes'(
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  nome VARCHAR(45),
  funcionario_id INT,
  FOREIGN KEY (funcionario_id) REFERENCES funcionarios(id)
);

 ____________________________
| id | nome | funcionario_id |
|____|______|________________|
0 registro

Code and Logic.

The logic is that every time we register a customer, we look for an employee to associate with his / her account, the Employee Search is as follows:

  • If registered customer searches existing in the registry
  • Otherwise if there is near the search queue based on the time
  • If it does not exist next, fetch the first from the queue

Based on this rule, I built the following code: (Detail in comments)

// Altere CPF e Variável $turno para testes
$novoCliente = Array(
   'cpf' => '66666666668',
   'nome' => 'Fulano Pereira Pinto',
   'funcionario_id' => null
);

$turno = 2; // 1 - Manhã | 2 - Tarde

// Define variável para armazenar funcionário
$funcId = null;


// Consulta se o cliente tem cadastro com base no CPF e pega o funcionário associado
$stmt = $con->prepare("SELECT funcionario_id FROM clientes WHERE cpf = :cpf"); 
// Executa a query
$stmt->execute( Array(':cpf' => $novoCliente['cpf']) ); 

// Verifica se teve resultado, se sim armazena ID do funcionário
if ($stmt->rowCount() > 0)
   $funcId = $stmt->fetch(PDO::FETCH_ASSOC)['funcionario_id'];


// Se não tem cadastro
if (is_null($funcId)){

   // Pega o próximo funcionario da sequencia com base no turno
   // A query busca o funcionario que tem um ID MAIOR do que o ID que estiver
   // na tabela de turno no campo 'lastfunc', ou seja o próximo
   $sql  = "SELECT fu.id as id
            FROM funcionarios as fu
               INNER JOIN turnos as tu ON tu.id = fu.turno_id
            WHERE 
               fu.id > tu.lastfunc AND
               fu.turno_id = :turno
            ORDER BY fu.id ASC LIMIT 1";
   $stmt = $con->prepare($sql);
   $stmt->execute( [':turno' => $turno] ); // Executa a query

   // Se teve resultado armazena o ID do funcionário
   if ($stmt->rowCount() > 0)
      $funcId = $stmt->fetch(PDO::FETCH_ASSOC)['id'];
}

// Se a regra anterior não teve resultado é porque
// chegou no último da fila e não tem próximo
// ou porque não tem nenhum id no campo 'lastfunc' da tabela 'turno'
// Então executa a regra seguinte
if (is_null($funcId)){

   // Seleciona o primeiro funcionario
   $sql  = "SELECT id FROM funcionarios ORDER BY id ASC LIMIT 1";
   $stmt = $con->prepare($sql); 
   $stmt->execute(); // Executa a query

   // Se teve resultado armazena o ID do funcionário
   if ($stmt->rowCount() > 0)
      $funcId = $stmt->fetch(PDO::FETCH_ASSOC)['id'];

  // Se não houver funcionar é porque não existe funcionário cadastrado
}

if (is_null($funcId)){
   // Se não pegou nenhum funcionário interrompe a execução do código
   exit('Erro: Nenhum funcionário pode ser associado ao cliente. Cadastro interrompido.');
} else {
   // Se encontrou algum funcionário atualiza os dados do cliente
   $novoCliente['funcionario_id'] = $funcId;
}

// Insere o funcionário no banco com os dados
$stmt = $con->prepare("INSERT INTO clientes (cpf, nome, funcionario_id) VALUES (:cpf, :nome, :funcionario)"); 
// Executa a query
$res = $stmt->execute( 
   Array(
      ':cpf' => $novoCliente['cpf'],
      ':nome' => $novoCliente['nome'],
      ':funcionario' => $novoCliente['funcionario_id']
   ) 
); 


if ($res){
   // Essa parte é muito IMPORTANTE
   // Tens que armazenar o ID do funcionário utilizado no turno dele,
   // para que a fila ande, pois é com base nesse campo que verificamos a 
   // posição da fila e então pegamos o próximo.
   $stmt = $con->prepare("UPDATE turnos SET lastfunc = :lfunc WHERE id = :turno"); 
   $res = $stmt->execute( 
      Array(
         ':lfunc' => $funcId,
         ':turno' => $turno
      ) 
   );
}


echo $res ? 'Sucesso' : 'Erro';

Result

Note: The first record left without an employee ID because I forgot to update the variable $novoCliente['funcionario_id'] before the INSERT of the client.

    
08.07.2015 / 20:38