Espelho de ponto

Fala galera… estou com um problema de logica e nao consigo pensar em uma solução prática, a mais proxima foi criar uma lista dentro de outra…

Tenho uma tabela ponto (idPonto, dataPonto, horaPonto, pisPonto);

ex:
1, 2021-07-01, 08:00, 12345678910
2, 2021-07-01, 12:00, 12345678910
3, 2021-07-01, 14:00, 12345678910
4, 2021-07-01, 18:00, 12345678910

isso se repete durante a semana… mas enfim, o que gostaria de fazer é exibir isso assim

01/07/2021 | 08:00 | 12:00 | 14:00 | 18:00:

Algumas pessoas nao vao ter as 4 marcaçoes certinho, e tem gente que vai ter mais de 4 no mesmo dia.

Alguem tem alguma dica/ideia de como posso fazer isso?

Você pode fazer um ArrayList de datas, e dentro de cada uma um ArrayList de StringBuilder, que você adicionaria uma marcação a cada vez que o funcionário passar pelo ponto.

Talvez não seja a solução mais elegante, mas é uma forma.

Uma solução seria usar um Map onde a chave é a data e o valor seria uma lista de pontos. Isso resolveria seu problema. Ex.:

Map<LocalDate, List<Ponto>> batidasDoDia = new HashMap<>();

Com isso, vc bastaria agrupar os pontos por data.


Porém, gosto mais da abordagem de usar classes bem definidas para representar algo. Por exemplo, vc poderia ter uma classe com o nome PontoDia que teria 2 propriedades: data e a lista de pontos. E nessa classe vc poderia manter a lógica de agrupar os pontos de determinado dia, assim como métodos para tratar esses dados de forma mais fácil.

Uma classe assim te ajuda a ter um controle melhor sobre esses dados, assim como manter coerência. Por exemplo, ao criar um PontoDia de uma lista de pontos, vc poderia ter uma validação que impediria que tivessem pontos de datas diferentes. Assim como já manter a lista de pontos na ordem de acordo com o a hora do ponto.

1 curtida

Montei esse exemplo aqui para exemplificar a ideia que postei antes:

Num primeiro momento, pode parecer muito código apenas para controlar uma lista de pontos por data, mas dependendo do tamanho do sistema, pode trazer grandes benefícios ao evoluir ou corrigir algo. Sem falar que facilita na hora de criar testes unitários.

Qualquer dica para melhorar a ideia no código é sempre muito bem vinda!

public static void main(String[] args) throws Exception {
	// Lista de pontos para testes
	List<Ponto> pontos = new ArrayList<>();
	
	// Experimente colocar datas diferentes e alterar a ordem dos horários
	// O código está preparado para tratar pontos de datas diferentes e manter a ordem do horário do ponto
	pontos.add(new Ponto(1, LocalDate.parse("2021-07-01"), LocalTime.parse("08:00"), 1));
	pontos.add(new Ponto(2, LocalDate.parse("2021-07-01"), LocalTime.parse("12:00"), 1));
	pontos.add(new Ponto(3, LocalDate.parse("2021-07-01"), LocalTime.parse("14:00"), 1));
	pontos.add(new Ponto(4, LocalDate.parse("2021-07-01"), LocalTime.parse("18:00"), 1));
	
	PontoDiaFactory pontoDiaFactory = new PontoDiaFactory();
	PontoDia pontoDia = pontoDiaFactory.create(pontos);
	
	// Esse é um exemplo de método utilitário que foi abstraído na classe PontoDia
	// além dele, vc pode criar outros que possam ser úteis ao manipular os pontos de um determinado dia
	System.out.println(pontoDia.getData() + " -> " + pontoDia.getHorariosAsText());
}
/**
 * Classe responsáve apenas por criar o ponto de dia, deixando essa lógica de criação separada
 * Essa lógica poderia ser dentro da própria classe PontoDia, se preferir
 */
static class PontoDiaFactory {
	
	public PontoDia create(List<Ponto> pontos) {
		Map<LocalDate,List<Ponto>> map = pontos.stream().collect(groupingBy(Ponto::getDataPonto));
		
		if (map.size() > 1) {
			throw new IllegalStateException("Não é possível criar um ponto do dia para pontos de datas diferentes: " + map.keySet());
		}
		
		Map.Entry<LocalDate, List<Ponto>> entry = map.entrySet().iterator().next();
		return new PontoDia(entry.getKey(), entry.getValue());
	}
}
/**
 * Classe que representa os pontos de um determinado dia
 */
static class PontoDia {
    private final LocalDate data;
    private final List<Ponto> pontos;
    
	public PontoDia(LocalDate data, List<Ponto> pontos) {
		this.data = data;
		this.pontos = pontos;
		this.pontos.sort(Comparator.comparing(Ponto::getHoraPonto));
	}

	public LocalDate getData() {
		return data;
	}

	public List<Ponto> getPontos() {
		return pontos;
	}
	
	public String getHorariosAsText() {
		return pontos.stream().map(p -> p.getHoraPonto().toString()).collect(Collectors.joining(", "));
	}
}
/**
 * Classe ponto que é uma entidade que representa a tabela Ponto do banco
 */
static class Ponto {
	private final int idPonto;
	private final LocalDate dataPonto;
	private final LocalTime horaPonto;
	private final int pisPonto;
	
	public Ponto(int idPonto, LocalDate dataPonto, LocalTime horaPonto, int pisPonto) {
		this.idPonto = idPonto;
		this.dataPonto = dataPonto;
		this.horaPonto = horaPonto;
		this.pisPonto = pisPonto;
	}
	
	public int getIdPonto() {
		return idPonto;
	}
	public LocalDate getDataPonto() {
		return dataPonto;
	}
	public LocalTime getHoraPonto() {
		return horaPonto;
	}
	public int getPisPonto() {
		return pisPonto;
	}
}

@Lucas_Camara

Muito show sua ideia, curti muito vou usar provavelmente na proxima parte…

mas analisando melhor o doc onde é feito o import do ponto, percebi uma coisa, ele ja vem “ordenado”,

consegui simplificar cruzando os dados de ponto de determinado PIS entre duas datas especificas, e uma tabela de escala, listo os pontos de acordo com a escala… funcionou…

${escala.getDataEscala() == ponto.getDataPonto() ? ponto.getHoraPonto() : ‘’}

se a data do ponto, for igual a da escala, ele inclui o ponto naquela linha.

pra “ordenar” por garantia, bastou um order by dataPonto, horaPonto no SQL…

Fazendo assim, consegui mandar pra narnia a necessidade de ordenar tudo pra salvar no banco de forma ordenada…

                        <c:forEach var="escala" items="${escala}">
                            <tr class="align-middle ${escala.getTipoEscala().getCorStatus()}">
                                <td>${escala.getDataEscala()} | ${escala.getTipoEscala().getNomeStatus()}</td>
                                <c:forEach var="ponto" items="${pontos}">
                                 
                                    ${escala.getDataEscala() == ponto.getDataPonto() ? ponto.getHoraPonto() : ''}
                                    

                                </c:forEach>
                            </tr>
                        </c:forEach>

Segue o techo da JSP onde a gambiarra funcionou kkkkk

@Lucas_Camara

Provavelmente na versao 2.0 vou usar a sua ideia, porque do jeito que fiz atualmente, estou gastando bastante processamento nessa listagem, porque percorro a lista em todas as linhas. Vou buscar performar melhor…

1 curtida