|
@@ -12,22 +12,6 @@ import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
@Controller
|
|
@Controller
|
|
|
public class VergleichController {
|
|
public class VergleichController {
|
|
|
- private final ObjectMapper om;
|
|
|
|
|
- private final SchemaValidationService validator;
|
|
|
|
|
- private final JsonNavigationService jsonNavigationService;
|
|
|
|
|
- private final DataComparisonService comparisonService;
|
|
|
|
|
- private final VergleichDataExtractor dataExtractor;
|
|
|
|
|
-
|
|
|
|
|
- public VergleichController(ObjectMapper om, SchemaValidationService validator,
|
|
|
|
|
- JsonNavigationService jsonNavigationService,
|
|
|
|
|
- DataComparisonService comparisonService,
|
|
|
|
|
- VergleichDataExtractor dataExtractor) {
|
|
|
|
|
- this.om = om;
|
|
|
|
|
- this.validator = validator;
|
|
|
|
|
- this.jsonNavigationService = jsonNavigationService;
|
|
|
|
|
- this.comparisonService = comparisonService;
|
|
|
|
|
- this.dataExtractor = dataExtractor;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
@GetMapping("/test")
|
|
@GetMapping("/test")
|
|
|
public String test(
|
|
public String test(
|
|
@@ -43,306 +27,10 @@ public class VergleichController {
|
|
|
return "test";
|
|
return "test";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @PostMapping("/vergleich")
|
|
|
|
|
- public String vergleich(
|
|
|
|
|
- @RequestParam String leftJson,
|
|
|
|
|
- @RequestParam String rightJson,
|
|
|
|
|
- @RequestParam(required = false, defaultValue = "true") boolean validate,
|
|
|
|
|
- @RequestParam(required = false, defaultValue = "haushalt-einkommen") String schemaName,
|
|
|
|
|
- @RequestParam(required = false) String leftVorgangId,
|
|
|
|
|
- @RequestParam(required = false) String leftZeitraumId,
|
|
|
|
|
- @RequestParam(required = false) String rightZeitraumId,
|
|
|
|
|
- @RequestParam(required = false) String personId,
|
|
|
|
|
- @RequestParam(required = false) String kunde,
|
|
|
|
|
- @RequestHeader(value = "X-Kunde", required = false) String kundeHeader,
|
|
|
|
|
- Model model) throws Exception {
|
|
|
|
|
-
|
|
|
|
|
- String activeKunde = resolveActiveKunde(kunde, kundeHeader);
|
|
|
|
|
-
|
|
|
|
|
- JsonNode left = om.readTree(leftJson);
|
|
|
|
|
- JsonNode right = om.readTree(rightJson);
|
|
|
|
|
-
|
|
|
|
|
- if (validate) {
|
|
|
|
|
- List<String> err = new ArrayList<>();
|
|
|
|
|
- err.addAll(validator.validate(left, schemaName));
|
|
|
|
|
- err.addAll(validator.validate(right, schemaName));
|
|
|
|
|
- if (!err.isEmpty()) {
|
|
|
|
|
- model.addAttribute("schemaErrors", err);
|
|
|
|
|
- model.addAttribute("leftJson", leftJson);
|
|
|
|
|
- model.addAttribute("rightJson", rightJson);
|
|
|
|
|
- model.addAttribute("validate", validate);
|
|
|
|
|
- model.addAttribute("schemaName", schemaName);
|
|
|
|
|
- return "test";
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // --- Rechts (Master) Zeitraum wählen ---
|
|
|
|
|
- List<Z> zeitrechte = jsonNavigationService.extractZeitraeume(right);
|
|
|
|
|
- if (zeitrechte.isEmpty()) throw new IllegalArgumentException("Right JSON hat keine Zeiträume");
|
|
|
|
|
- if (rightZeitraumId == null) rightZeitraumId = zeitrechte.get(0).id;
|
|
|
|
|
- JsonNode rightZeitraum = jsonNavigationService.findZeitraumById(right, rightZeitraumId);
|
|
|
|
|
-
|
|
|
|
|
- // --- Find the stammvorgang that contains the selected zeitraum ---
|
|
|
|
|
- JsonNode stammvorgangJsonNode = jsonNavigationService.findStammvorgangByZeitraumId(right, rightZeitraumId);
|
|
|
|
|
- StammvorgangInfo stammvorgangRight = jsonNavigationService.createStammvorgangInfo(stammvorgangJsonNode);
|
|
|
|
|
-
|
|
|
|
|
- // --- Extract stammakte info if available ---
|
|
|
|
|
- StammakteInfo stammakteRight = jsonNavigationService.extractStammakteInfo(right);
|
|
|
|
|
-
|
|
|
|
|
- // --- Links (Baseline) Kandidaten & Auswahl ---
|
|
|
|
|
- List<Vorgang> leftCand = jsonNavigationService.parseLeftCandidates(left);
|
|
|
|
|
- List<Z> leftZ = List.of();
|
|
|
|
|
- JsonNode leftZeitraum = null;
|
|
|
|
|
- if (!leftCand.isEmpty()) {
|
|
|
|
|
- if (leftVorgangId == null) leftVorgangId = leftCand.get(0).id;
|
|
|
|
|
- final String finalLeftVorgangId = leftVorgangId;
|
|
|
|
|
- leftZ = leftCand.stream().filter(v -> v.id.equals(finalLeftVorgangId)).findFirst().orElse(leftCand.get(0)).zeitraeume;
|
|
|
|
|
- if (leftZeitraumId == null && !leftZ.isEmpty()) leftZeitraumId = leftZ.get(0).id;
|
|
|
|
|
- if (leftZeitraumId != null) leftZeitraum = jsonNavigationService.findZeitraumById(jsonNavigationService.getRootOfVorgang(left, leftVorgangId), leftZeitraumId);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // --- Personenliste rechts + Default personId ---
|
|
|
|
|
- List<PersonRef> personenRight = jsonNavigationService.listRightPersons(rightZeitraum);
|
|
|
|
|
- if (personId == null && !personenRight.isEmpty()) personId = personenRight.get(0).id;
|
|
|
|
|
-
|
|
|
|
|
- // --- Personen-Tabelle (UNION via person.id) ---
|
|
|
|
|
- PersonComparisonContext context = createPersonComparisonContext(rightZeitraum, leftZeitraum, personId);
|
|
|
|
|
- List<MitgliedRow> mitgliederRows = context.personenPairs.entrySet().stream()
|
|
|
|
|
- .map(e -> dataExtractor.buildMitgliedRow(e.getKey(), e.getValue().right, e.getValue().left))
|
|
|
|
|
- .sorted(Comparator.comparing(MitgliedRow::personId))
|
|
|
|
|
- .toList();
|
|
|
|
|
-
|
|
|
|
|
- // --- Model füllen & rendern ---
|
|
|
|
|
- model.addAttribute("leftJson", leftJson);
|
|
|
|
|
- model.addAttribute("rightJson", rightJson);
|
|
|
|
|
- model.addAttribute("validate", validate);
|
|
|
|
|
- model.addAttribute("schemaName", schemaName);
|
|
|
|
|
- model.addAttribute("leftCandidates", leftCand);
|
|
|
|
|
- model.addAttribute("leftZeitraeumeOfSelected", leftZ);
|
|
|
|
|
- model.addAttribute("leftVorgangId", leftVorgangId);
|
|
|
|
|
- model.addAttribute("leftZeitraumId", leftZeitraumId);
|
|
|
|
|
- model.addAttribute("zeitraeumeRight", zeitrechte);
|
|
|
|
|
- model.addAttribute("rightZeitraumId", rightZeitraumId);
|
|
|
|
|
- model.addAttribute("stammvorgangRight", stammvorgangRight);
|
|
|
|
|
- model.addAttribute("stammakteRight", stammakteRight);
|
|
|
|
|
- model.addAttribute("personenRight", personenRight);
|
|
|
|
|
- model.addAttribute("personId", personId);
|
|
|
|
|
- model.addAttribute("mitgliederRows", mitgliederRows);
|
|
|
|
|
- model.addAttribute("personLabel", context.personLabel);
|
|
|
|
|
- model.addAttribute("einkommenZeilen", context.einkommenZeilen);
|
|
|
|
|
- model.addAttribute("freibetragZeilen", context.freibetragZeilen);
|
|
|
|
|
- model.addAttribute("kitaZeilen", context.kitaZeilen);
|
|
|
|
|
- model.addAttribute("activeKunde", activeKunde);
|
|
|
|
|
- return "vergleich";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @PostMapping("/api/person-details")
|
|
|
|
|
- @ResponseBody
|
|
|
|
|
- public ResponseEntity<PersonDetailsResponse> getPersonDetails(
|
|
|
|
|
- @RequestParam String leftJson,
|
|
|
|
|
- @RequestParam String rightJson,
|
|
|
|
|
- @RequestParam String leftVorgangId,
|
|
|
|
|
- @RequestParam String leftZeitraumId,
|
|
|
|
|
- @RequestParam String rightZeitraumId,
|
|
|
|
|
- @RequestParam String personId) throws Exception {
|
|
|
|
|
-
|
|
|
|
|
- JsonNode left = om.readTree(leftJson);
|
|
|
|
|
- JsonNode right = om.readTree(rightJson);
|
|
|
|
|
-
|
|
|
|
|
- JsonNode rightZeitraum = jsonNavigationService.findZeitraumById(right, rightZeitraumId);
|
|
|
|
|
- JsonNode leftZeitraum = null;
|
|
|
|
|
- if (leftZeitraumId != null) {
|
|
|
|
|
- leftZeitraum = jsonNavigationService.findZeitraumById(jsonNavigationService.getRootOfVorgang(left, leftVorgangId), leftZeitraumId);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PersonComparisonContext context = createPersonComparisonContext(rightZeitraum, leftZeitraum, personId);
|
|
|
|
|
-
|
|
|
|
|
- PersonDetailsResponse response = new PersonDetailsResponse(
|
|
|
|
|
- personId,
|
|
|
|
|
- context.personLabel,
|
|
|
|
|
- context.einkommenZeilen,
|
|
|
|
|
- context.freibetragZeilen,
|
|
|
|
|
- context.kitaZeilen
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- return ResponseEntity.ok(response);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @PostMapping("/api/vorgang-change")
|
|
|
|
|
- @ResponseBody
|
|
|
|
|
- public ResponseEntity<VorgangChangeResponse> changeLeftVorgang(
|
|
|
|
|
- @RequestParam String leftJson,
|
|
|
|
|
- @RequestParam String rightJson,
|
|
|
|
|
- @RequestParam String rightZeitraumId,
|
|
|
|
|
- @RequestParam String personId,
|
|
|
|
|
- @RequestParam String newLeftVorgangId) throws Exception {
|
|
|
|
|
-
|
|
|
|
|
- JsonNode left = om.readTree(leftJson);
|
|
|
|
|
- JsonNode right = om.readTree(rightJson);
|
|
|
|
|
-
|
|
|
|
|
- // --- Links (Baseline) Kandidaten & neue Auswahl ---
|
|
|
|
|
- List<Vorgang> leftCand = jsonNavigationService.parseLeftCandidates(left);
|
|
|
|
|
-
|
|
|
|
|
- final String finalLeftVorgangId = newLeftVorgangId;
|
|
|
|
|
- List<Z> leftZ = leftCand.stream()
|
|
|
|
|
- .filter(v -> v.id.equals(finalLeftVorgangId))
|
|
|
|
|
- .findFirst()
|
|
|
|
|
- .orElse(leftCand.get(0))
|
|
|
|
|
- .zeitraeume;
|
|
|
|
|
-
|
|
|
|
|
- // Ersten Zeitraum des neuen Vorgangs als Default wählen
|
|
|
|
|
- String newLeftZeitraumId = !leftZ.isEmpty() ? leftZ.get(0).id : null;
|
|
|
|
|
-
|
|
|
|
|
- JsonNode rightZeitraum = jsonNavigationService.findZeitraumById(right, rightZeitraumId);
|
|
|
|
|
- JsonNode leftZeitraum = null;
|
|
|
|
|
- if (newLeftZeitraumId != null) {
|
|
|
|
|
- leftZeitraum = jsonNavigationService.findZeitraumById(jsonNavigationService.getRootOfVorgang(left, newLeftVorgangId), newLeftZeitraumId);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PersonComparisonContext context = createPersonComparisonContext(rightZeitraum, leftZeitraum, personId);
|
|
|
|
|
- List<MitgliedRow> mitgliederRows = context.personenPairs.entrySet().stream()
|
|
|
|
|
- .map(e -> dataExtractor.buildMitgliedRow(e.getKey(), e.getValue().right, e.getValue().left))
|
|
|
|
|
- .sorted(Comparator.comparing(MitgliedRow::personId))
|
|
|
|
|
- .toList();
|
|
|
|
|
-
|
|
|
|
|
- VorgangChangeResponse response = new VorgangChangeResponse(
|
|
|
|
|
- newLeftVorgangId,
|
|
|
|
|
- newLeftZeitraumId,
|
|
|
|
|
- leftZ,
|
|
|
|
|
- mitgliederRows,
|
|
|
|
|
- personId,
|
|
|
|
|
- context.personLabel,
|
|
|
|
|
- context.einkommenZeilen,
|
|
|
|
|
- context.freibetragZeilen,
|
|
|
|
|
- context.kitaZeilen
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- return ResponseEntity.ok(response);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @PostMapping("/api/zeitraum-change")
|
|
|
|
|
- @ResponseBody
|
|
|
|
|
- public ResponseEntity<ZeitraumChangeResponse> changeLeftZeitraum(
|
|
|
|
|
- @RequestParam String leftJson,
|
|
|
|
|
- @RequestParam String rightJson,
|
|
|
|
|
- @RequestParam String leftVorgangId,
|
|
|
|
|
- @RequestParam String rightZeitraumId,
|
|
|
|
|
- @RequestParam String personId,
|
|
|
|
|
- @RequestParam String newLeftZeitraumId) throws Exception {
|
|
|
|
|
-
|
|
|
|
|
- JsonNode left = om.readTree(leftJson);
|
|
|
|
|
- JsonNode right = om.readTree(rightJson);
|
|
|
|
|
-
|
|
|
|
|
- JsonNode rightZeitraum = jsonNavigationService.findZeitraumById(right, rightZeitraumId);
|
|
|
|
|
- JsonNode leftZeitraum = null;
|
|
|
|
|
- if (newLeftZeitraumId != null) {
|
|
|
|
|
- leftZeitraum = jsonNavigationService.findZeitraumById(jsonNavigationService.getRootOfVorgang(left, leftVorgangId), newLeftZeitraumId);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PersonComparisonContext context = createPersonComparisonContext(rightZeitraum, leftZeitraum, personId);
|
|
|
|
|
- List<MitgliedRow> mitgliederRows = context.personenPairs.entrySet().stream()
|
|
|
|
|
- .map(e -> dataExtractor.buildMitgliedRow(e.getKey(), e.getValue().right, e.getValue().left))
|
|
|
|
|
- .sorted(Comparator.comparing(MitgliedRow::personId))
|
|
|
|
|
- .toList();
|
|
|
|
|
-
|
|
|
|
|
- ZeitraumChangeResponse response = new ZeitraumChangeResponse(
|
|
|
|
|
- newLeftZeitraumId,
|
|
|
|
|
- mitgliederRows,
|
|
|
|
|
- personId,
|
|
|
|
|
- context.personLabel,
|
|
|
|
|
- context.einkommenZeilen,
|
|
|
|
|
- context.freibetragZeilen,
|
|
|
|
|
- context.kitaZeilen
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- return ResponseEntity.ok(response);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// ===== Private Helper Methods =====
|
|
// ===== Private Helper Methods =====
|
|
|
|
|
|
|
|
private String resolveActiveKunde(String kunde, String kundeHeader) {
|
|
private String resolveActiveKunde(String kunde, String kundeHeader) {
|
|
|
return kunde != null ? kunde : kundeHeader;
|
|
return kunde != null ? kunde : kundeHeader;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private PersonComparisonContext createPersonComparisonContext(JsonNode rightZeitraum, JsonNode leftZeitraum, String personId) {
|
|
|
|
|
- // Personen-Tabelle (UNION via person.id)
|
|
|
|
|
- Map<String, Pair<JsonNode, JsonNode>> personenPairs = comparisonService.unionByKey(
|
|
|
|
|
- jsonNavigationService.personsArray(rightZeitraum),
|
|
|
|
|
- jsonNavigationService.personsArray(leftZeitraum),
|
|
|
|
|
- n -> n.path("person").path("id").asText()
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- // Details für ausgewählte Person
|
|
|
|
|
- JsonNode rightPerson = personenPairs.getOrDefault(personId, new Pair<>(null, null)).right;
|
|
|
|
|
- JsonNode leftPerson = personenPairs.getOrDefault(personId, new Pair<>(null, null)).left;
|
|
|
|
|
-
|
|
|
|
|
- String personLabel = createPersonLabel(rightPerson, leftPerson);
|
|
|
|
|
- Map<String, String> personNameById = createPersonNameMap(rightZeitraum, leftZeitraum);
|
|
|
|
|
-
|
|
|
|
|
- // Einkommen / Freibeträge / Kita: jeweils UNION per id
|
|
|
|
|
- List<EinkommenZeile> einkommenZeilen = dataExtractor.buildEinkommenZeilen(rightPerson, leftPerson);
|
|
|
|
|
- List<FreibetragZeile> freibetragZeilen = dataExtractor.buildFreibetragZeilen(rightPerson, leftPerson);
|
|
|
|
|
- List<KitaZeile> kitaZeilen = dataExtractor.buildKitaZeilen(rightPerson, leftPerson, personNameById);
|
|
|
|
|
-
|
|
|
|
|
- return new PersonComparisonContext(personenPairs, personLabel, einkommenZeilen, freibetragZeilen, kitaZeilen);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private String createPersonLabel(JsonNode rightPerson, JsonNode leftPerson) {
|
|
|
|
|
- if (rightPerson != null) {
|
|
|
|
|
- return rightPerson.path("person").path("nachname").asText("") + ", " +
|
|
|
|
|
- rightPerson.path("person").path("vorname").asText("");
|
|
|
|
|
- } else if (leftPerson != null) {
|
|
|
|
|
- return leftPerson.path("person").path("nachname").asText("") + ", " +
|
|
|
|
|
- leftPerson.path("person").path("vorname").asText("");
|
|
|
|
|
- }
|
|
|
|
|
- return "(keine Person)";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Map<String, String> createPersonNameMap(JsonNode rightZeitraum, JsonNode leftZeitraum) {
|
|
|
|
|
- Map<String, String> personNameById = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- // Add all persons from right (current) JSON
|
|
|
|
|
- List<PersonRef> personenRight = jsonNavigationService.listRightPersons(rightZeitraum);
|
|
|
|
|
- personenRight.forEach(p -> personNameById.put(p.id, p.label));
|
|
|
|
|
-
|
|
|
|
|
- // Add persons from left JSON that are not already in the map
|
|
|
|
|
- if (leftZeitraum != null) {
|
|
|
|
|
- List<PersonRef> personenLeft = jsonNavigationService.listRightPersons(leftZeitraum);
|
|
|
|
|
- personenLeft.stream()
|
|
|
|
|
- .filter(p -> !personNameById.containsKey(p.id))
|
|
|
|
|
- .forEach(p -> personNameById.put(p.id, p.label));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return personNameById;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // ===== Helper Classes =====
|
|
|
|
|
-
|
|
|
|
|
- private record PersonComparisonContext(
|
|
|
|
|
- Map<String, Pair<JsonNode, JsonNode>> personenPairs,
|
|
|
|
|
- String personLabel,
|
|
|
|
|
- List<EinkommenZeile> einkommenZeilen,
|
|
|
|
|
- List<FreibetragZeile> freibetragZeilen,
|
|
|
|
|
- List<KitaZeile> kitaZeilen
|
|
|
|
|
- ) {}
|
|
|
|
|
-
|
|
|
|
|
- // ===== Public Records =====
|
|
|
|
|
-
|
|
|
|
|
- public record Z(String id, String beginn, String ende) {}
|
|
|
|
|
- public record Vorgang(String id, String vorgangstyp, List<Z> zeitraeume) {}
|
|
|
|
|
- public record PersonRef(String id, String label) {}
|
|
|
|
|
- public record StammvorgangInfo(String id, String vorgangstyp, String vorgangsstatus) {}
|
|
|
|
|
- public record StammakteInfo(String aktenzeichen, String antragstellername, String antragstellerGeburtsdatum, String anschrift) {}
|
|
|
|
|
- public record PersonDetailsResponse(String personId, String personLabel, List<EinkommenZeile> einkommenZeilen, List<FreibetragZeile> freibetragZeilen, List<KitaZeile> kitaZeilen) {}
|
|
|
|
|
- public record VorgangChangeResponse(String leftVorgangId, String leftZeitraumId, List<Z> leftZeitraeume, List<MitgliedRow> mitgliederRows, String personId, String personLabel, List<EinkommenZeile> einkommenZeilen, List<FreibetragZeile> freibetragZeilen, List<KitaZeile> kitaZeilen) {}
|
|
|
|
|
- public record ZeitraumChangeResponse(String leftZeitraumId, List<MitgliedRow> mitgliederRows, String personId, String personLabel, List<EinkommenZeile> einkommenZeilen, List<FreibetragZeile> freibetragZeilen, List<KitaZeile> kitaZeilen) {}
|
|
|
|
|
-
|
|
|
|
|
- public static final class Pair<R, L> {
|
|
|
|
|
- public final R right;
|
|
|
|
|
- public final L left;
|
|
|
|
|
- public Pair(R r, L l) {
|
|
|
|
|
- right = r;
|
|
|
|
|
- left = l;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|