Added ability to store elections and parties

This commit is contained in:
2023-07-09 15:06:21 +02:00
parent 1987064fbe
commit ed0ef018a5
7 changed files with 364 additions and 0 deletions
@@ -0,0 +1,78 @@
package de.twomartens.wahlrecht.controller.v1;
import de.twomartens.wahlrecht.mapper.v1.ElectionMapper;
import de.twomartens.wahlrecht.model.dto.v1.Election;
import de.twomartens.wahlrecht.service.ElectionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Collection;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.factory.Mappers;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/wahlrecht/v1")
@Tag(name = "Elections", description = "all requests relating to elections")
public class ElectionController {
private final ElectionMapper mapper = Mappers.getMapper(ElectionMapper.class);
private final ElectionService service;
@Operation(
summary = "Returns all stored elections",
responses = {
@ApiResponse(responseCode = "200",
description = "Returns all stored elections",
content = {@Content(
mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = Election.class)))}
)
}
)
@GetMapping(value = "/elections", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Collection<Election>> getElections() {
List<Election> elections = service.getElections().stream().map(mapper::mapToExternal).toList();
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(elections);
}
@Operation(
summary = "Stores a new election",
responses = {
@ApiResponse(responseCode = "201",
description = "Election was created"),
@ApiResponse(responseCode = "200",
description = "Election was modified"),
@ApiResponse(responseCode = "401",
description = "Unauthorized",
content = {@Content(
mediaType = "plain/text")}
)
}
)
@PutMapping("/election")
@SecurityRequirement(name = "basicAuth")
public ResponseEntity<?> putElection(@RequestBody Election election) {
boolean createdNew = service.storeElection(mapper.mapToDB(election));
return createdNew
? new ResponseEntity<>(HttpStatus.CREATED)
: new ResponseEntity<>(HttpStatus.OK);
}
}
@@ -0,0 +1,94 @@
package de.twomartens.wahlrecht.controller.v1;
import de.twomartens.wahlrecht.mapper.v1.PartyInElectionMapper;
import de.twomartens.wahlrecht.model.dto.ErrorMessage;
import de.twomartens.wahlrecht.model.dto.v1.PartyInElection;
import de.twomartens.wahlrecht.service.PartyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Collection;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.factory.Mappers;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/wahlrecht/v1")
@Tag(name = "Parties", description = "all requests relating to parties")
public class PartyController {
private final PartyInElectionMapper mapper = Mappers.getMapper(PartyInElectionMapper.class);
private final PartyService service;
@Operation(
summary = "Returns all stored parties for given election name",
responses = {
@ApiResponse(responseCode = "200",
description = "Returns all stored parties",
content = {@Content(
mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = PartyInElection.class)))}
),
@ApiResponse(responseCode = "404",
description = "No parties found",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorMessage.class)
)
}
)
}
)
@GetMapping(value = "/parties/by-election-name/{electionName}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Collection<PartyInElection>> getPartiesByElectionName(
@PathVariable @Parameter(description = "the election name", example = "Bezirkswahl 2019") String electionName) {
List<PartyInElection> parties = service.getPartiesByElectionName(electionName).stream()
.map(mapper::mapToExternal)
.toList();
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(parties);
}
@Operation(
summary = "Stores a new party in an election",
responses = {
@ApiResponse(responseCode = "201",
description = "Party was created"),
@ApiResponse(responseCode = "200",
description = "Party was modified"),
@ApiResponse(responseCode = "401",
description = "Unauthorized",
content = {@Content(
mediaType = "plain/text")}
)
}
)
@PutMapping("/party")
@SecurityRequirement(name = "basicAuth")
public ResponseEntity<?> putElection(@RequestBody PartyInElection party) {
boolean createdNew = service.storeParty(mapper.mapToDB(party));
return createdNew
? new ResponseEntity<>(HttpStatus.CREATED)
: new ResponseEntity<>(HttpStatus.OK);
}
}
@@ -0,0 +1,27 @@
package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Candidate;
import de.twomartens.wahlrecht.repository.CandidateRepository;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
public class CandidateService {
private final CandidateRepository repository;
public Candidate storeCandidate(@NonNull Candidate candidate) {
Optional<Candidate> foundOptional = repository.findByName(candidate.getName());
if (foundOptional.isPresent()) {
Candidate found = foundOptional.get();
found.setProfession(candidate.getProfession());
return repository.save(found);
} else {
return repository.save(candidate);
}
}
}
@@ -0,0 +1,33 @@
package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Constituency;
import de.twomartens.wahlrecht.repository.ConstituencyRepository;
import java.util.Collection;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class ConstituencyService {
private final ConstituencyRepository repository;
public Collection<Constituency> getConstituencies() {
return repository.findAll();
}
public Constituency storeConstituency(@NonNull Constituency constituency) {
Optional<Constituency> foundOptional = repository
.findByElectionNameAndNumber(constituency.getElectionName(), constituency.getNumber());
if (foundOptional.isPresent()) {
Constituency found = foundOptional.get();
found.setNumberOfSeats(constituency.getNumberOfSeats());
found.setName(constituency.getName());
constituency = found;
}
return repository.save(constituency);
}
}
@@ -0,0 +1,47 @@
package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Constituency;
import de.twomartens.wahlrecht.model.db.Election;
import de.twomartens.wahlrecht.repository.ElectionRepository;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
public class ElectionService {
private final ElectionRepository electionRepository;
private final ConstituencyService constituencyService;
public Collection<Election> getElections() {
return electionRepository.findAll();
}
public boolean storeElection(@NonNull Election election) {
boolean createdNew = true;
String electionName = election.getName();
Optional<Election> existingElectionOptional = electionRepository.findByName(electionName);
Collection<Constituency> constituencies = new ArrayList<>();
election.getConstituencies()
.forEach(constituency -> constituencies.add(
constituencyService.storeConstituency(constituency)));
if (existingElectionOptional.isPresent()) {
Election existing = existingElectionOptional.get();
existing.setDay(election.getDay());
existing.setTotalNumberOfSeats(election.getTotalNumberOfSeats());
existing.setVotingThreshold(election.getVotingThreshold());
election = existing;
createdNew = false;
}
election.setConstituencies(constituencies);
electionRepository.save(election);
return createdNew;
}
}
@@ -0,0 +1,32 @@
package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Candidate;
import de.twomartens.wahlrecht.model.db.Nomination;
import de.twomartens.wahlrecht.repository.NominationRepository;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
public class NominationService {
private final NominationRepository repository;
private final CandidateService candidateService;
public Nomination storeNomination(Nomination nomination) {
Optional<Nomination> existingOptional = repository
.findByNameAndElectionNameAndPartyAbbreviation(nomination.getName(),
nomination.getElectionName(), nomination.getPartyAbbreviation());
Collection<Candidate> candidates = new ArrayList<>();
nomination.getCandidates()
.forEach(candidate -> candidates.add(candidateService.storeCandidate(candidate)));
if (existingOptional.isPresent()) {
nomination = existingOptional.get();
}
nomination.setCandidates(candidates);
return repository.save(nomination);
}
}
@@ -0,0 +1,53 @@
package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Nomination;
import de.twomartens.wahlrecht.model.db.PartyInElection;
import de.twomartens.wahlrecht.repository.PartyRepository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
@RequiredArgsConstructor
@Service
public class PartyService {
private final PartyRepository partyRepository;
private final NominationService nominationService;
public Collection<PartyInElection> getPartiesByElectionName(String electionName) {
Collection<PartyInElection> parties = partyRepository.findByElectionName(electionName);
if (parties.isEmpty()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "no party found for " + electionName);
}
return parties;
}
public boolean storeParty(PartyInElection partyInElection) {
boolean createdNew = true;
Optional<PartyInElection> existingOptional = partyRepository
.findByAbbreviationAndElectionName(partyInElection.getName(),
partyInElection.getElectionName());
Map<Integer, Nomination> constituencyNominations = new HashMap<>();
partyInElection.getConstituencyNominations()
.forEach((key, value) -> constituencyNominations.put(key,
nominationService.storeNomination(value)));
if (existingOptional.isPresent()) {
PartyInElection existing = existingOptional.get();
existing.setName(partyInElection.getName());
partyInElection = existing;
createdNew = false;
}
partyInElection.setConstituencyNominations(constituencyNominations);
partyInElection.setOverallNomination(
nominationService.storeNomination(partyInElection.getOverallNomination()));
partyRepository.save(partyInElection);
return createdNew;
}
}