Problema de lógica para criação de agenda de horários [RESOLVIDO]

7 respostas
brunoprod

Senhores, boa tarde.

Estou tentando implementar uma agenda médica, onde existem horários pré-definidos de 50 em 50 minutos ( o tempo de uma consulta ), para isto utilizo a seguinte estrutura (foi uma idéia minha, aceito dicas de mudança rs).

TB_CONSULTA

int seq -> (numero sequencial, PK)
int id_horario
date data

TB_HORARIO

int id
varchar(5) descrição (08:00, 08:50, 09:40, 10:30, 11:20 . etc… são 15 horários)

Para recuperar os horários ocupados em uma data é muito fácil, basta fazer um join entre as duas tabelas, pois a tabela TB_CONSULTA sempre possui o id do horario agendado, bastando então recuperar a descrição do horario na tabela TB_HORARIO e exibir em tela, numa listagem.

So que nesta mesma listagem, eu também gostaria de exibir os horarios que estão desocupados, mas eu queria colocar tudo numa ordem sequencial, por exemplo:

DATA HORÁRIO SITUAÇÃO

09/03/2012 08:00 ocupado
09/03/2012 08:50 livre
09/03/2012 09:40 ocupado
09/03/2012 10:30 ocupado
09/03/2012 11:20 livre

Na tela, o usuário escolheria uma data para verificar qual a situação de todos os horários daquele dia, então a pesquisa seria feita. De tal forma, eu pensei em criar uma coleção de VO’s (VoConsulta) com 15 VO’s (pois são 15 horários pré-definidos), onde esses vo’s seriam populados com os dados dos horários do dia. De tal forma, se o horario estiver vazio, o vo conterá populado nele apenas a data e horario. Se o horario estiver ocupado, o vo terá populado outros dados também, como o nome do paciente, do médico, etc.

Até aí tudo bem, o problema é se o usuário pesquisar por um intervalo de datas. Por exemplo de 09/03/2012 a 20/03/2012. Eu teria que criar 15 Vo’s para cada dia, e se o intervalo fosse maior seriam incontáveis então a quantidade de vo’s abrigados em uma collection, o que deixaria o processo muito muito lento (provavelmente).

Finalmente, a minha pergunta é, alguém tem uma idéia melhor que essa para resolver esta situação? Levando em conta que o que eu preciso é exibir a listagem de horários, separados por data (paginação)… ? Este processo que estou usando parece ser muito “braçal”, mas não consegui pensar em outra coisa, e já pesquisei e não achei nada que pudesse me suprir.

Obrigado pela atenção de todos.

7 Respostas

ribclauport

Estava, aqui analisando seu post, e tipo só para constar se seu sistema for web, ja existem soluções prontas para isso em prime faces por exemplo…
Mas se for no braço, pense comigo, para que duas tabelas? eu faria somente uma tabela com por exemplo horários. Mas de qualquer forma pense comigo, você
usa somente uma pesquisa certo, faz um select com um where entre as duas datas de pesquisa, e na hora de popular a estrutura de dados, você usa um TreeSet,
no seu VO você implementa comparable usando seu campo de Data, você pode usar um Gregorain Calendar para isso…, qual seria a dificuldade?

Poste ae para nós discutirmos.

ribclauport

TB_CONSULTA

int seq -> (numero sequencial, PK)
int id_horario
date data

TB_HORARIO

int id
varchar(5) descrição (08:00, 08:50, 09:40, 10:30, 11:20 . etc… são 15 horários)

Bom, o que acha de mudarmos o campo descricao de tb_horario para horario_agendamento e colocar tipo Date?
Também "TB_CONSULTA" acredito que poderia se chamar "AGENDA", desta forma esta tabela teria o id de TB_HORARIO como chave estrangeira, e o campo "data" poderia se chamar data_de_agendamento, ou seja seria a data que foi agendado o horário, por exemplo dia 18 às 9h agendou horário para dia 27…

A mudança destes campos se dizem a respeito da ordenação entende… pois descrição seria necessário depois fazer conversões…

Veja bem na hora de popular o TreeSet, voce poderia dar no banco um left join, desta forma seu set viria a esquerda todos os horarios e a direita null, se não houver
horário, quando iterar o seu TreeSet para popular com a pesquisa, vai estar pronto!

ribclauport

Eu mesmo li, e não consegui entender direito o que escveri então vou colar como acho que pode ser o banco:

CREATE  TABLE `titan`.`TB_HORARIO` (

  `ID` INT NOT NULL ,

  `horario_agendamento` VARCHAR(45) NULL ,

  PRIMARY KEY (`ID`) );


  =================================================================================================
CREATE  TABLE `titan`.`AGENDA` (

  `ID` INT NOT NULL ,

  `ID_HORARIO` INT NULL ,

  `DATA_DE_ADENDAMENTO` TIMESTAMP NULL ,

  PRIMARY KEY (`ID`) ,

  INDEX `FK_TB_HORARIO` (`ID_HORARIO` ASC) );
ribclauport

Acabei fazendo o procedimento aqui vou postar os scripts que usei e as saidas que obtive acredito que seria isso que você precisa:

CREATE TABLE tb_horario(
   ID int(11) NOT NULL AUTO_INCREMENT,
   horario_agendamento time DEFAULT NULL,
   PRIMARY KEY (ID)
 )
================================================================================

CREATE TABLE agenda (
   ID int(11) NOT NULL AUTO_INCREMENT,
   ID_HORARIO int(11) DEFAULT NULL,
   DATA_DE_AGENDAMENTO timestamp NULL DEFAULT NULL,
   DATA date DEFAULT NULL,
   PRIMARY KEY (ID),
   KEY FK_TB_HORARIO (ID_HORARIO)
 )

Depois os inserts que usei:

===============================================================================
insert into titan.tb_horario(horario_agendamento) values(080000);
insert into titan.tb_horario(horario_agendamento) values(085000);
insert into titan.tb_horario(horario_agendamento) values(094000);
insert into titan.tb_horario(horario_agendamento) values(103000);
insert into titan.tb_horario(horario_agendamento) values(112000);
insert into titan.tb_horario(horario_agendamento) values(121000);
insert into titan.tb_horario(horario_agendamento) values(130000);
insert into titan.tb_horario(horario_agendamento) values(135000);
insert into titan.tb_horario(horario_agendamento) values(144000);
insert into titan.tb_horario(horario_agendamento) values(153000);
insert into titan.tb_horario(horario_agendamento) values(162000);
insert into titan.tb_horario(horario_agendamento) values(171000);
insert into titan.tb_horario(horario_agendamento) values(180000);
 
 ===============================================================================
 insert into `agenda` VALUES (1,17,'2012-03-10 22:13:57','2012-10-10'),(2,23,'2012-03-10 22:23:14','2012-12-10');
 ===============================================================================

Abaixo o select que irá usar o left Join para trazer os horários com e sem agendamento do dia e o resultado obtido:

select * from tb_horario a
	left join agenda b
  on 
(a.id = b.id_horario and data='2012-10-10')
 
 ===============================================================================
ID| horario_agendamento|ID|ID_HORARIOA|DATA_DE_AGENDAMENTO|DATA
17	08:00:00			1  17	       2012-03-10          19:13:57	2012-10-10
18	08:50:00				
19	09:40:00				
20	10:30:00				
21	11:20:00				
22	12:10:00				
23	13:00:00				
24	13:50:00				
25	14:40:00				
26	15:30:00				
27	16:20:00				
28	17:10:00				
29	18:00:00				
 =============================================================================

Agora depois disso é só modelar para objetos, sendo assim criei um objeto agenda, o
qual será populado em uma lista, e fazer a lógica para se vier nulo colocar uma descrição,
abaixo segue o código:

package entyties;

import java.sql.Time;
import java.util.Date;

public class Agenda {
	private Time horario;
	private Date data;
	public Time getHorario() {
		return horario;
	}
	public void setHorario(Time horario) {
		this.horario = horario;
	}
	public Date getData() {
		return data;
	}
	public void setData(Date data) {
		this.data = data;
	}

}

===============================================================================

package entyties;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class TesteAgenda {
	public static void main(String[] args) throws SQLException,
			ClassNotFoundException {
		ResultSet rs = null;
		String sql = "select a.horario_agendamento" +
				" horarios," +
				" b.data dia" +
				" from tb_horario a "+
			    "left join agenda b on "+
			    "(a.id = b.id_horario and b.data=?)";
		PreparedStatement pstmt = Conexao.conexao().prepareStatement(sql);
				
		pstmt.setString(1, "2012-10-10");
		rs = pstmt.executeQuery();

		List<Agenda> agendametosDia = new ArrayList<Agenda>();
		while (rs.next()) {
			Agenda a = new Agenda();
			a.setHorario(rs.getTime(1));
			a.setData(rs.getDate(2));
			agendametosDia.add(a);
		}
		for(Agenda agendamento : agendametosDia){
			String hora =  (String) (agendamento.getData() == null ? "disponivel" : agendamento.getData().toString());
			System.out.println(agendamento.getHorario() +"  "+ hora);
		}

	}

}

Resultado obtido no final de todo o procedimento:

08:00:00 2012-10-10 08:50:00 disponivel 09:40:00 disponivel 10:30:00 disponivel 11:20:00 disponivel 12:10:00 disponivel 13:00:00 disponivel 13:50:00 disponivel 14:40:00 disponivel 15:30:00 disponivel 16:20:00 disponivel 17:10:00 disponivel 18:00:00 disponivel

Acredito que seria isso, se resolver seu problema edite o post e coloque [Resolvido]
Até.

brunoprod

Meu caro amigo, desculpe a demora em responder, esses dias fiquei sem acesso.
Mas enfim, muito obrigado ficou ótimo, na verdade eu acho que o meu maior problema era não
ter usado o left join , pois com este está facilitando muito a visualização dos horários vagos, trazendo
tudo junto de uma vez, e eu não sabia como utilizar.

No caso de o usuário buscar entre duas datas, vc acha que seria melhor tipo eu fazer uma paginação por demanda?
Como eu te disse tenho a preocupação da lista ficar muito grande (buscando com data >= dd/MM/yyyy and data <= dd/MM/yyyy).
Ou você acha que nesse caso seria interessante limitar a busca por quantidade de dias ?

ribclauport

Sem dúvida o uso de paginação é o indicado!

brunoprod

Amigo muito obrigado ! Problema resolvido !

Criado 9 de março de 2012
Ultima resposta 13 de mar. de 2012
Respostas 7
Participantes 2