Skip to content

Commit

Permalink
WoopSicredi#6 - Criação do serviço de apuração
Browse files Browse the repository at this point in the history
+ Criação dos testes unitários e de integração da apuração dos votos.
  • Loading branch information
ruddypersivo committed Nov 25, 2019
1 parent 71a57e4 commit 4f337ca
Show file tree
Hide file tree
Showing 14 changed files with 213 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ public enum MensagemValidacaoVotacaoEnum {
BAD_REQUEST("bad.request"),
ASSOCIADO_JA_VOTOU_NESTA_PAUTA("associado.ja.votou.nesta.pauta"),
SOMENTE_SESSOES_ATIVAS_ESTAO_APTAS_A_RECEBEREM_VOTOS("somente.sessoes.ativas.estao.aptas.a.receberem.votos"),
ASSOCIADO_IMPEDIDO_DE_VOTAR("associado.impedido.de.votar");
ASSOCIADO_IMPEDIDO_DE_VOTAR("associado.impedido.de.votar"),
SESSAO_NAO_INICIOU("sessao.nao.iniciou"),
SESSAO_ESTA_ATIVA("sessao.esta.ativa");

private String codigo;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import javax.transaction.Transactional;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -16,28 +20,35 @@
import br.com.sicredi.votacaoapi.domains.pauta.dto.AbrirSessaoResponse;
import br.com.sicredi.votacaoapi.domains.pauta.dto.CriarPautaRequest;
import br.com.sicredi.votacaoapi.domains.pauta.dto.CriarPautaResponse;
import br.com.sicredi.votacaoapi.domains.pauta.dto.ResultadoVotacaoResponse;
import br.com.sicredi.votacaoapi.domains.pauta.dto.VotoRequest;
import br.com.sicredi.votacaoapi.domains.pauta.dto.VotoResponse;
import br.com.sicredi.votacaoapi.domains.pauta.service.AbrirSessaoService;
import br.com.sicredi.votacaoapi.domains.pauta.service.ApuracaoDaVotacaoPautaService;
import br.com.sicredi.votacaoapi.domains.pauta.service.CriarPautaService;
import br.com.sicredi.votacaoapi.domains.pauta.service.VotoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping("pauta")
@Api(tags = "TopicEndpoint")
public class TopicController {
@Api(tags = "PautaEndpoint")
public class PautaController {

private AbrirSessaoService abrirSessaoService;

private ApuracaoDaVotacaoPautaService apuracaoDaVotacaoPautaService;

private CriarPautaService criarPautaService;

private VotoService votoService;

@Autowired
public TopicController(AbrirSessaoService abrirSessaoService, CriarPautaService criarPautaService, VotoService votoService) {
public PautaController(AbrirSessaoService abrirSessaoService,
ApuracaoDaVotacaoPautaService apuracaoDaVotacaoPautaService, CriarPautaService criarPautaService,
VotoService votoService) {
this.abrirSessaoService = abrirSessaoService;
this.apuracaoDaVotacaoPautaService = apuracaoDaVotacaoPautaService;
this.criarPautaService = criarPautaService;
this.votoService = votoService;
}
Expand All @@ -46,15 +57,15 @@ public TopicController(AbrirSessaoService abrirSessaoService, CriarPautaService
@PostMapping("/criar")
@ResponseBody
@Transactional
public ResponseEntity<CriarPautaResponse> create(@Valid @RequestBody CriarPautaRequest request) {
public ResponseEntity<CriarPautaResponse> criar(@Valid @RequestBody CriarPautaRequest request) {
return ResponseEntity.ok().body(CriarPautaResponse.converterEmDTO(criarPautaService.criar(request.getNome())));
}

@ApiOperation(value = "Abrir sessão")
@PutMapping("/abrirSessao")
@ResponseBody
@Transactional
public ResponseEntity<AbrirSessaoResponse> openSession(@Valid @RequestBody AbrirSessaoRequest request) {
public ResponseEntity<AbrirSessaoResponse> abrirSessao(@Valid @RequestBody AbrirSessaoRequest request) {
return ResponseEntity.ok().body(AbrirSessaoResponse
.converterEmDTO(abrirSessaoService.abrirSessao(request.getPautaId(), request.getDuracaoEmMinutos())));
}
Expand All @@ -63,8 +74,17 @@ public ResponseEntity<AbrirSessaoResponse> openSession(@Valid @RequestBody Abrir
@PostMapping("/votar")
@ResponseBody
@Transactional
public ResponseEntity<VotoResponse> vote(@Valid @RequestBody VotoRequest request) {
return ResponseEntity.ok().body(votoService.votar(request.getPautaId(), request.getAssociado(), request.getDecisao()));
public ResponseEntity<VotoResponse> votar(@Valid @RequestBody VotoRequest request) {
return ResponseEntity.ok()
.body(votoService.votar(request.getPautaId(), request.getAssociado(), request.getDecisao()));
}

@ApiOperation(value = "Apuração da votação da pauta")
@GetMapping("/apuracao/{pautaId}")
@ResponseBody
public ResponseEntity<ResultadoVotacaoResponse> apuracao(
@PathVariable @NotNull(message = "{pautaId.invalido}") @Positive(message = "{valor.nao.pode.ser.negativo}") Long pautaId) {
return ResponseEntity.ok().body(apuracaoDaVotacaoPautaService.apurar(pautaId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class AbrirSessaoRequest {

@NotNull(message = "{pautaId.invalido}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Associado {

@NotNull(message = "{associado.id.invalido}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import br.com.sicredi.votacaoapi.domains.pauta.model.Pauta;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CriarPautaRequest {

@NotBlank(message = "{nome.nao.vazio}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
import br.com.sicredi.votacaoapi.domains.pauta.model.Pauta;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class PautaDTO {

private Long pautaId;
Expand All @@ -31,7 +33,7 @@ public class PautaDTO {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime fimVotacao;

public static PautaDTO turnsIntoDTO(Pauta pauta) {
public static PautaDTO converterEmDTO(Pauta pauta) {
return new PautaDTO(pauta.getId(), pauta.getNome(), pauta.getInicioVotacao(), pauta.getFimVotacao());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package br.com.sicredi.votacaoapi.domains.pauta.dto;

import br.com.sicredi.votacaoapi.domains.pauta.model.Pauta;
import br.com.sicredi.votacaoapi.domains.pauta.model.validations.TipoDeResultadoDaVotacao;
import lombok.Getter;

@Getter
public class ResultadoVotacaoResponse {

private PautaDTO pauta;

private TipoDeResultadoDaVotacao votingResult;

public ResultadoVotacaoResponse(Pauta pauta, TipoDeResultadoDaVotacao votingResult) {
this.pauta = PautaDTO.converterEmDTO(pauta);
this.votingResult = votingResult;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class VotoRequest {

@NotNull(message = "{pautaId.invalido}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class VotoResponse {
private Boolean decision;

public VotoResponse(Pauta pauta, Associado associado, Boolean decisao) {
this.pautaDTO = PautaDTO.turnsIntoDTO(pauta);
this.pautaDTO = PautaDTO.converterEmDTO(pauta);
this.associado = associado;
this.decision = decisao;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package br.com.sicredi.votacaoapi.domains.pauta.model.validations;

public enum TipoDeResultadoDaVotacao {

SIM,
NAO,
EMPATE,
SEM_VOTOS;

public static TipoDeResultadoDaVotacao deAcordoComAQuantidadeDeVotos(Integer quantidadeDeVotos) {
if (quantidadeDeVotos == null) {
return SEM_VOTOS;
} else if (quantidadeDeVotos == 0) {
return EMPATE;
} else if (quantidadeDeVotos < 0) {
return NAO;
}
return SIM;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package br.com.sicredi.votacaoapi.domains.pauta.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import br.com.sicredi.votacaoapi.application.error.BusinessException;
import br.com.sicredi.votacaoapi.application.error.MensagemValidacaoVotacaoEnum;
import br.com.sicredi.votacaoapi.domains.pauta.dto.ResultadoVotacaoResponse;
import br.com.sicredi.votacaoapi.domains.pauta.model.Pauta;
import br.com.sicredi.votacaoapi.domains.pauta.model.validations.TipoDeResultadoDaVotacao;

@Service
public class ApuracaoDaVotacaoPautaService {

private RecuperarPautaService recuperarPautaService;

@Autowired
public ApuracaoDaVotacaoPautaService(RecuperarPautaService recuperarPautaService) {
this.recuperarPautaService = recuperarPautaService;
}

public ResultadoVotacaoResponse apurar(Long pautaId) {
Pauta pauta = recuperarPautaService.retornarPautaPorId(pautaId);
if (!pauta.temSessaoIniciada()) {
throw new BusinessException(MensagemValidacaoVotacaoEnum.SESSAO_NAO_INICIOU);
} else if (pauta.temSessaoAtiva()) {
throw new BusinessException(MensagemValidacaoVotacaoEnum.SESSAO_ESTA_ATIVA);
}

TipoDeResultadoDaVotacao votingResult = TipoDeResultadoDaVotacao.deAcordoComAQuantidadeDeVotos(
pauta.getVotos()
.stream()
.map(v -> v.getDecisao() ? 1 : -1)
.reduce(0, (subtotal, element) -> subtotal + element)
);

return new ResultadoVotacaoResponse(pauta, votingResult);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package br.com.sicredi.votacaoapi.domains.pauta.service;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import br.com.sicredi.votacaoapi.StringUtils;
import br.com.sicredi.votacaoapi.application.error.BusinessException;
import br.com.sicredi.votacaoapi.application.error.MensagemValidacaoVotacaoEnum;
import br.com.sicredi.votacaoapi.application.error.RecursoNaoEncontradoException;
import br.com.sicredi.votacaoapi.domains.pauta.dto.ResultadoVotacaoResponse;
import br.com.sicredi.votacaoapi.domains.pauta.model.Pauta;
import br.com.sicredi.votacaoapi.domains.pauta.model.validations.TipoDeResultadoDaVotacao;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class GetPollCountServiceTest {

@Autowired
private TestRestTemplate restTemplate;

@MockBean
private ApuracaoDaVotacaoPautaService apuracaoDaVotacaoPautaService;

@Test
public void apurarQuandoSessaoEstiverFinalizadaDeveriaRetornarCodigoDeStatus200Ok() {

Pauta pauta = new Pauta();
pauta.setId(1L);
pauta.setNome(StringUtils.spaces(100));
pauta.abrirSessao(null);

ResultadoVotacaoResponse resultadoVotacaoResponse = new ResultadoVotacaoResponse(pauta, TipoDeResultadoDaVotacao.SIM);
BDDMockito.when(apuracaoDaVotacaoPautaService.apurar(1L)).thenReturn(resultadoVotacaoResponse);

ResponseEntity<String> response = restTemplate.getForEntity("/pauta/apuracao/1", String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(200);

}

@Test
public void apurarQuandoPautaENulaDeveriaRetornarCodigoDeStatus400BadRequest() {
ResponseEntity<String> response = restTemplate.getForEntity("/pauta/apuracao/A", String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(400);
}

@Test
public void apurarQuandoCodigoDaPautaENegativaDeveriaRetornarCodigoDeStatus400BadRequest() {
ResponseEntity<String> response = restTemplate.getForEntity("/pauta/apuracao/-1", String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(400);
}

@Test
public void apurarQuandoPautaNaoExisteDeveriaRetornarCodigoDeStatus404ResourceNotFound() {
BDDMockito.when(apuracaoDaVotacaoPautaService.apurar(1L)).thenThrow(new RecursoNaoEncontradoException(MensagemValidacaoVotacaoEnum.PAUTA_NAO_EXISTE));
ResponseEntity<String> response = restTemplate.getForEntity("/pauta/apuracao/1", String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(404);
}

@Test
public void apurarQuandoSessaoNaoFoiIniciadaDeveriaRetornarCodigoDeStatus400BadRequest() {
BDDMockito.when(apuracaoDaVotacaoPautaService.apurar(1L)).thenThrow(new BusinessException(MensagemValidacaoVotacaoEnum.SESSAO_NAO_INICIOU));
ResponseEntity<String> response = restTemplate.getForEntity("/pauta/apuracao/1", String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(400);
}

@Test
public void apurarQuandoSessaoEstiverAtivaDeveriaRetornarCodigoDeStatus400BadRequest() {
BDDMockito.when(apuracaoDaVotacaoPautaService.apurar(1L)).thenThrow(new BusinessException(MensagemValidacaoVotacaoEnum.SESSAO_ESTA_ATIVA));
ResponseEntity<String> response = restTemplate.getForEntity("/pauta/apuracao/1", String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(400);
}

}
4 changes: 3 additions & 1 deletion src/test/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ associado.invalido=Por favor informe o associado
decisao.invalido=Por favor informe o voto
associado.ja.votou.nesta.pauta=Membro já votou nesta pauta
somente.sessoes.ativas.estao.aptas.a.receberem.votos=Somente sessões ativas estão aptas a receberem votos
associado.impedido.de.votar=Associado impedido de votar
associado.impedido.de.votar=Associado impedido de votar
sessao.nao.iniciou=Sessão não foi iniciada
sessao.esta.ativa=Sessão está ativa
4 changes: 3 additions & 1 deletion src/test/resources/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ associado.invalido=Please enter the associate
decisao.invalido=Please enter the vote
associado.ja.votou.nesta.pauta=Member Already Voted On This Topic
somente.sessoes.ativas.estao.aptas.a.reveberem.votos=Only in active sessions you can vote
associado.impedido.de.votar=Associate barred from voting
associado.impedido.de.votar=Associate barred from voting
sessao.nao.iniciou=Session Not Started
sessao.esta.ativa=Session Is Active

0 comments on commit 4f337ca

Please sign in to comment.