From aa9bdd514ab90d0da0391b879255a22c29450e9a Mon Sep 17 00:00:00 2001 From: Szymon Szukalski Date: Thu, 25 Jul 2024 20:36:11 +1000 Subject: Validate import payload and return create/update stats - Add validation to /import payload - Move import logic to service bean - Track whether entities have been created or update - Report number of created and updated entities as return value for the import endpoint - Add some test coverage to exercise the validators --- .../markr/dto/AggregateResponseDTO.java | 117 +++++++++++++++++++++ .../markr/dto/AggregatedTestResultsDTO.java | 117 --------------------- .../markr/dto/ImportResponseDTO.java | 115 ++++++++++++++++++++ .../stileeducation/markr/dto/MCQTestResultDTO.java | 15 +++ .../markr/dto/MCQTestResultsDTO.java | 2 + .../stileeducation/markr/dto/SummaryMarksDTO.java | 12 ++- 6 files changed, 259 insertions(+), 119 deletions(-) create mode 100644 src/main/java/com/stileeducation/markr/dto/AggregateResponseDTO.java delete mode 100644 src/main/java/com/stileeducation/markr/dto/AggregatedTestResultsDTO.java create mode 100644 src/main/java/com/stileeducation/markr/dto/ImportResponseDTO.java (limited to 'src/main/java/com/stileeducation/markr/dto') diff --git a/src/main/java/com/stileeducation/markr/dto/AggregateResponseDTO.java b/src/main/java/com/stileeducation/markr/dto/AggregateResponseDTO.java new file mode 100644 index 0000000..7232174 --- /dev/null +++ b/src/main/java/com/stileeducation/markr/dto/AggregateResponseDTO.java @@ -0,0 +1,117 @@ +package com.stileeducation.markr.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AggregateResponseDTO { + + private double mean; + private double stddev; + private double min; + private double max; + private double p25; + private double p50; + private double p75; + private int count; + + // Getters and Setters + public double getMean() { + return mean; + } + + public void setMean(double mean) { + this.mean = mean; + } + + public double getStddev() { + return stddev; + } + + public void setStddev(double stddev) { + this.stddev = stddev; + } + + public double getMin() { + return min; + } + + public void setMin(double min) { + this.min = min; + } + + public double getMax() { + return max; + } + + public void setMax(double max) { + this.max = max; + } + + public double getP25() { + return p25; + } + + public void setP25(double p25) { + this.p25 = p25; + } + + public double getP50() { + return p50; + } + + public void setP50(double p50) { + this.p50 = p50; + } + + public double getP75() { + return p75; + } + + public void setP75(double p75) { + this.p75 = p75; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AggregateResponseDTO that = (AggregateResponseDTO) o; + return Double.compare(mean, that.mean) == 0 + && Double.compare(stddev, that.stddev) == 0 + && Double.compare(min, that.min) == 0 + && Double.compare(max, that.max) == 0 + && Double.compare(p25, that.p25) == 0 + && Double.compare(p50, that.p50) == 0 + && Double.compare(p75, that.p75) == 0 + && count == that.count; + } + + @Override + public int hashCode() { + return Objects.hash(mean, stddev, min, max, p25, p50, p75, count); + } + + @Override + public String toString() { + return "AggregatedTestResultsDTO{" + + "mean=" + mean + + ", stddev=" + stddev + + ", min=" + min + + ", max=" + max + + ", p25=" + p25 + + ", p50=" + p50 + + ", p75=" + p75 + + ", count=" + count + + '}'; + } +} diff --git a/src/main/java/com/stileeducation/markr/dto/AggregatedTestResultsDTO.java b/src/main/java/com/stileeducation/markr/dto/AggregatedTestResultsDTO.java deleted file mode 100644 index f5970c3..0000000 --- a/src/main/java/com/stileeducation/markr/dto/AggregatedTestResultsDTO.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.stileeducation.markr.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; - -import java.util.Objects; - -@JsonInclude(JsonInclude.Include.NON_NULL) -public class AggregatedTestResultsDTO { - - private double mean; - private double stddev; - private double min; - private double max; - private double p25; - private double p50; - private double p75; - private int count; - - // Getters and Setters - public double getMean() { - return mean; - } - - public void setMean(double mean) { - this.mean = mean; - } - - public double getStddev() { - return stddev; - } - - public void setStddev(double stddev) { - this.stddev = stddev; - } - - public double getMin() { - return min; - } - - public void setMin(double min) { - this.min = min; - } - - public double getMax() { - return max; - } - - public void setMax(double max) { - this.max = max; - } - - public double getP25() { - return p25; - } - - public void setP25(double p25) { - this.p25 = p25; - } - - public double getP50() { - return p50; - } - - public void setP50(double p50) { - this.p50 = p50; - } - - public double getP75() { - return p75; - } - - public void setP75(double p75) { - this.p75 = p75; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AggregatedTestResultsDTO that = (AggregatedTestResultsDTO) o; - return Double.compare(mean, that.mean) == 0 - && Double.compare(stddev, that.stddev) == 0 - && Double.compare(min, that.min) == 0 - && Double.compare(max, that.max) == 0 - && Double.compare(p25, that.p25) == 0 - && Double.compare(p50, that.p50) == 0 - && Double.compare(p75, that.p75) == 0 - && count == that.count; - } - - @Override - public int hashCode() { - return Objects.hash(mean, stddev, min, max, p25, p50, p75, count); - } - - @Override - public String toString() { - return "AggregatedTestResultsDTO{" + - "mean=" + mean + - ", stddev=" + stddev + - ", min=" + min + - ", max=" + max + - ", p25=" + p25 + - ", p50=" + p50 + - ", p75=" + p75 + - ", count=" + count + - '}'; - } -} diff --git a/src/main/java/com/stileeducation/markr/dto/ImportResponseDTO.java b/src/main/java/com/stileeducation/markr/dto/ImportResponseDTO.java new file mode 100644 index 0000000..8613865 --- /dev/null +++ b/src/main/java/com/stileeducation/markr/dto/ImportResponseDTO.java @@ -0,0 +1,115 @@ +package com.stileeducation.markr.dto; + +public class ImportResponseDTO { + + private String status; + private String message; + private ImportData data; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ImportData getData() { + return data; + } + + public void setData(ImportData data) { + this.data = data; + } + + public static class ImportData { + private int studentsCreated = 0; + private int studentsUpdated = 0; + + private int testsCreated = 0; + private int testsUpdated = 0; + + private int testResultsCreated = 0; + private int testResultsUpdated = 0; + + public int getStudentsCreated() { + return studentsCreated; + } + + public void setStudentsCreated(int studentsCreated) { + this.studentsCreated = studentsCreated; + } + + public int getStudentsUpdated() { + return studentsUpdated; + } + + public void setStudentsUpdated(int studentsUpdated) { + this.studentsUpdated = studentsUpdated; + } + + public int getTestsCreated() { + return testsCreated; + } + + public void setTestsCreated(int testsCreated) { + this.testsCreated = testsCreated; + } + + public int getTestsUpdated() { + return testsUpdated; + } + + public void setTestsUpdated(int testsUpdated) { + this.testsUpdated = testsUpdated; + } + + public int getTestResultsCreated() { + return testResultsCreated; + } + + public void setTestResultsCreated(int testResultsCreated) { + this.testResultsCreated = testResultsCreated; + } + + public int getTestResultsUpdated() { + return testResultsUpdated; + } + + public void setTestResultsUpdated(int testResultsUpdated) { + this.testResultsUpdated = testResultsUpdated; + } + + public void incrementStudentsCreated() { + this.studentsCreated++; + } + + public void incrementStudentsUpdated() { + this.studentsUpdated++; + } + + public void incrementTestsCreated() { + this.testsCreated++; + } + + public void incrementTestsUpdated() { + this.testsUpdated++; + } + + public void incrementTestResultsCreated() { + this.testResultsCreated++; + } + + public void incrementTestResultsUpdated() { + this.testResultsUpdated++; + } + } +} diff --git a/src/main/java/com/stileeducation/markr/dto/MCQTestResultDTO.java b/src/main/java/com/stileeducation/markr/dto/MCQTestResultDTO.java index b227fe3..da6a0e1 100644 --- a/src/main/java/com/stileeducation/markr/dto/MCQTestResultDTO.java +++ b/src/main/java/com/stileeducation/markr/dto/MCQTestResultDTO.java @@ -1,5 +1,8 @@ package com.stileeducation.markr.dto; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; @@ -9,11 +12,23 @@ import java.util.Objects; @XmlRootElement(name = "mcq-test-result") public class MCQTestResultDTO { + @NotBlank private String scannedOn; + + @NotBlank(message = "First name is mandatory") private String firstName; + + @NotBlank(message = "Last name is mandatory") private String lastName; + + @NotBlank(message = "Last name is mandatory") private String studentNumber; + + @NotBlank(message = "Test id is mandatory") private String testId; + + @Valid + @NotNull private SummaryMarksDTO summaryMarks; @XmlAttribute(name = "scanned-on") diff --git a/src/main/java/com/stileeducation/markr/dto/MCQTestResultsDTO.java b/src/main/java/com/stileeducation/markr/dto/MCQTestResultsDTO.java index e9ee8a7..fb77125 100644 --- a/src/main/java/com/stileeducation/markr/dto/MCQTestResultsDTO.java +++ b/src/main/java/com/stileeducation/markr/dto/MCQTestResultsDTO.java @@ -1,5 +1,6 @@ package com.stileeducation.markr.dto; +import jakarta.validation.Valid; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; @@ -9,6 +10,7 @@ import java.util.Objects; @XmlRootElement(name = "mcq-test-results") public class MCQTestResultsDTO { + @Valid private List mcqTestResults; @XmlElement(name = "mcq-test-result") diff --git a/src/main/java/com/stileeducation/markr/dto/SummaryMarksDTO.java b/src/main/java/com/stileeducation/markr/dto/SummaryMarksDTO.java index a67d19c..788eea0 100644 --- a/src/main/java/com/stileeducation/markr/dto/SummaryMarksDTO.java +++ b/src/main/java/com/stileeducation/markr/dto/SummaryMarksDTO.java @@ -1,5 +1,7 @@ package com.stileeducation.markr.dto; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlRootElement; @@ -7,8 +9,14 @@ import java.util.Objects; @XmlRootElement(name = "summary-marks") public class SummaryMarksDTO { - private int available; - private int obtained; + + @NotNull(message = "Available marks must not be null") + @Min(value = 0, message = "Available marks must be non-negative") + private Integer available; + + @NotNull(message = "Obtained marks must not be null") + @Min(value = 0, message = "Obtained marks must be non-negative") + private Integer obtained; @XmlAttribute(name = "available") public int getAvailable() { -- cgit v1.2.3