From d3e2f66ffef216260e974f12827e1e8f40749ab5 Mon Sep 17 00:00:00 2001 From: Justin Konecny Date: Thu, 13 May 2021 12:21:26 -0400 Subject: [PATCH 1/8] Start data vis endpoints --- .../IProtectedDataProcessor.java | 13 +++ .../dto/data/MetricsCountryResponse.java | 73 +++++++++++++ .../dto/data/MetricsSchoolResponse.java | 51 +++++++++ .../com/codeforcommunity/rest/ApiRouter.java | 8 +- .../codeforcommunity/rest/FailureHandler.java | 22 ++-- .../authenticated/ProtectedDataRouter.java | 63 +++++++++++ .../com/codeforcommunity/ServiceMain.java | 10 +- .../dataaccess/SchoolDatabaseOperations.java | 69 ++++++++++++ .../ProtectedDataProcessorImpl.java | 102 ++++++++++++++++++ .../ProtectedSchoolProcessorImpl.java | 79 +++++--------- 10 files changed, 424 insertions(+), 66 deletions(-) create mode 100644 api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java create mode 100644 api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java create mode 100644 api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java create mode 100644 api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java create mode 100644 service/src/main/java/com/codeforcommunity/dataaccess/SchoolDatabaseOperations.java create mode 100644 service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java diff --git a/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java new file mode 100644 index 00000000..5e240d82 --- /dev/null +++ b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java @@ -0,0 +1,13 @@ +package com.codeforcommunity.api.authenticated; + +import com.codeforcommunity.auth.JWTData; +import com.codeforcommunity.dto.data.MetricsCountryResponse; +import com.codeforcommunity.dto.data.MetricsSchoolResponse; +import com.codeforcommunity.enums.Country; + +public interface IProtectedDataProcessor { + + MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country country); + + MetricsSchoolResponse getFixedSchoolMetrics(JWTData userData, int schoolId); +} diff --git a/api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java b/api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java new file mode 100644 index 00000000..f0cd77bd --- /dev/null +++ b/api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java @@ -0,0 +1,73 @@ +package com.codeforcommunity.dto.data; + +public class MetricsCountryResponse { + private Integer countSchools; + private Integer countVolunteerAccounts; + private Integer countAdminAccounts; + private Float avgCountBooksPerStudent; + private Float avgCountStudentLibrariansPerSchool; + private Float percentSchoolsWithLibraries; + + public MetricsCountryResponse( + Integer countSchools, + Integer countVolunteerAccounts, + Integer countAdminAccounts, + Float avgCountBooksPerStudent, + Float avgCountStudentLibrariansPerSchool, + Float percentSchoolsWithLibraries) { + this.countSchools = countSchools; + this.countVolunteerAccounts = countVolunteerAccounts; + this.countAdminAccounts = countAdminAccounts; + this.avgCountBooksPerStudent = avgCountBooksPerStudent; + this.avgCountStudentLibrariansPerSchool = avgCountStudentLibrariansPerSchool; + this.percentSchoolsWithLibraries = percentSchoolsWithLibraries; + } + + public Integer getCountSchools() { + return countSchools; + } + + public void setCountSchools(Integer countSchools) { + this.countSchools = countSchools; + } + + public Integer getCountVolunteerAccounts() { + return countVolunteerAccounts; + } + + public void setCountVolunteerAccounts(Integer countVolunteerAccounts) { + this.countVolunteerAccounts = countVolunteerAccounts; + } + + public Integer getCountAdminAccounts() { + return countAdminAccounts; + } + + public void setCountAdminAccounts(Integer countAdminAccounts) { + this.countAdminAccounts = countAdminAccounts; + } + + public Float getAvgCountBooksPerStudent() { + return avgCountBooksPerStudent; + } + + public void setAvgCountBooksPerStudent(Float avgCountBooksPerStudent) { + this.avgCountBooksPerStudent = avgCountBooksPerStudent; + } + + public Float getAvgCountStudentLibrariansPerSchool() { + return avgCountStudentLibrariansPerSchool; + } + + public void setAvgCountStudentLibrariansPerSchool(Float avgCountStudentLibrariansPerSchool) { + this.avgCountStudentLibrariansPerSchool = avgCountStudentLibrariansPerSchool; + } + + public Float getPercentSchoolsWithLibraries() { + return percentSchoolsWithLibraries; + } + + public void setPercentSchoolsWithLibraries(Float percentSchoolsWithLibraries) { + this.percentSchoolsWithLibraries = percentSchoolsWithLibraries; + } +} diff --git a/api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java b/api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java new file mode 100644 index 00000000..50dda300 --- /dev/null +++ b/api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java @@ -0,0 +1,51 @@ +package com.codeforcommunity.dto.data; + +public class MetricsSchoolResponse { + private Float countBooksPerStudent; + private Integer countStudents; + private Integer countStudentLibrarians; + private Integer netBooksInOut; + + public MetricsSchoolResponse( + Float countBooksPerStudent, + Integer countStudents, + Integer countStudentLibrarians, + Integer netBooksInOut) { + this.countBooksPerStudent = countBooksPerStudent; + this.countStudents = countStudents; + this.countStudentLibrarians = countStudentLibrarians; + this.netBooksInOut = netBooksInOut; + } + + public Float getCountBooksPerStudent() { + return countBooksPerStudent; + } + + public void setCountBooksPerStudent(Float countBooksPerStudent) { + this.countBooksPerStudent = countBooksPerStudent; + } + + public Integer getCountStudents() { + return countStudents; + } + + public void setCountStudents(Integer countStudents) { + this.countStudents = countStudents; + } + + public Integer getCountStudentLibrarians() { + return countStudentLibrarians; + } + + public void setCountStudentLibrarians(Integer countStudentLibrarians) { + this.countStudentLibrarians = countStudentLibrarians; + } + + public Integer getNetBooksInOut() { + return netBooksInOut; + } + + public void setNetBooksInOut(Integer netBooksInOut) { + this.netBooksInOut = netBooksInOut; + } +} diff --git a/api/src/main/java/com/codeforcommunity/rest/ApiRouter.java b/api/src/main/java/com/codeforcommunity/rest/ApiRouter.java index 4da8321a..e9c10ecc 100644 --- a/api/src/main/java/com/codeforcommunity/rest/ApiRouter.java +++ b/api/src/main/java/com/codeforcommunity/rest/ApiRouter.java @@ -1,12 +1,14 @@ package com.codeforcommunity.rest; import com.codeforcommunity.api.authenticated.IProtectedCountryProcessor; +import com.codeforcommunity.api.authenticated.IProtectedDataProcessor; import com.codeforcommunity.api.authenticated.IProtectedSchoolProcessor; import com.codeforcommunity.api.authenticated.IProtectedUserProcessor; import com.codeforcommunity.api.unauthenticated.IAuthProcessor; import com.codeforcommunity.auth.JWTAuthorizer; import com.codeforcommunity.rest.subrouter.CommonRouter; import com.codeforcommunity.rest.subrouter.authenticated.ProtectedCountryRouter; +import com.codeforcommunity.rest.subrouter.authenticated.ProtectedDataRouter; import com.codeforcommunity.rest.subrouter.authenticated.ProtectedSchoolRouter; import com.codeforcommunity.rest.subrouter.authenticated.ProtectedUserRouter; import com.codeforcommunity.rest.subrouter.unauthenticated.AuthRouter; @@ -20,18 +22,21 @@ public class ApiRouter implements IRouter { private final ProtectedUserRouter protectedUserRouter; private final ProtectedCountryRouter protectedCountryRouter; private final ProtectedSchoolRouter protectedSchoolRouter; + private final ProtectedDataRouter protectedDataRouter; public ApiRouter( JWTAuthorizer jwtAuthorizer, IAuthProcessor authProcessor, IProtectedUserProcessor protectedUserProcessor, IProtectedCountryProcessor protectedCountryProcessor, - IProtectedSchoolProcessor protectedSchoolProcessor) { + IProtectedSchoolProcessor protectedSchoolProcessor, + IProtectedDataProcessor protectedDataProcessor) { this.commonRouter = new CommonRouter(jwtAuthorizer); this.authRouter = new AuthRouter(authProcessor); this.protectedUserRouter = new ProtectedUserRouter(protectedUserProcessor); this.protectedCountryRouter = new ProtectedCountryRouter(protectedCountryProcessor); this.protectedSchoolRouter = new ProtectedSchoolRouter(protectedSchoolProcessor); + this.protectedDataRouter = new ProtectedDataRouter(protectedDataProcessor); } /** Initialize a router and register all route handlers on it. */ @@ -57,6 +62,7 @@ private Router defineProtectedRoutes(Vertx vertx) { protectedSubRouter.mountSubRouter("/user", protectedUserRouter.initializeRouter(vertx)); protectedSubRouter.mountSubRouter("/countries", protectedCountryRouter.initializeRouter(vertx)); protectedSubRouter.mountSubRouter("/schools", protectedSchoolRouter.initializeRouter(vertx)); + protectedSubRouter.mountSubRouter("/data", protectedDataRouter.initializeRouter(vertx)); return protectedSubRouter; } diff --git a/api/src/main/java/com/codeforcommunity/rest/FailureHandler.java b/api/src/main/java/com/codeforcommunity/rest/FailureHandler.java index ac121198..cbf67c6a 100644 --- a/api/src/main/java/com/codeforcommunity/rest/FailureHandler.java +++ b/api/src/main/java/com/codeforcommunity/rest/FailureHandler.java @@ -48,12 +48,12 @@ public void handleMissingParameter(RoutingContext ctx, MissingParameterException } public void handleNoReportFound(RoutingContext ctx, NoReportFoundException e) { - String message = String.format("Report not found for school with id %d", e.getSchoolId()); + String message = String.format("Report not found for school with ID %d", e.getSchoolId()); end(ctx, message, 404); } public void handleNoReportByIdFound(RoutingContext ctx, NoReportByIdFoundException e) { - String message = String.format("Report not found for report with id %d", e.getReportId()); + String message = String.format("Report not found for report with ID %d", e.getReportId()); end(ctx, message, 404); } @@ -64,7 +64,8 @@ public void handleAdminOnlyRoute(RoutingContext ctx) { public void handleEmailAlreadyInUse(RoutingContext ctx, EmailAlreadyInUseException exception) { String message = - String.format("Error creating new user, given email %s already used", exception.getEmail()); + String.format( + "Error creating new user, given email '%s' already used", exception.getEmail()); end(ctx, message, 409); } @@ -72,7 +73,7 @@ public void handleEmailAlreadyInUse(RoutingContext ctx, EmailAlreadyInUseExcepti public void handleSchoolAlreadyExists(RoutingContext ctx, SchoolAlreadyExistsException e) { String message = String.format( - "School '%s' already exists in '%s'", e.getSchoolName(), e.getSchoolCountry()); + "School '%s' already exists in country '%s'", e.getSchoolName(), e.getSchoolCountry()); end(ctx, message, 409); } @@ -175,7 +176,7 @@ public void handleMalformedParameter(RoutingContext ctx, MalformedParameterExcep } public void handleUnknownCountry(RoutingContext ctx, UnknownCountryException exception) { - String message = String.format("Unknown country given: %s", exception.getUnknownCountry()); + String message = String.format("No country found with name %s", exception.getUnknownCountry()); end(ctx, message, 400); } @@ -183,7 +184,7 @@ public void handleUnknownSchoolContact( RoutingContext ctx, SchoolContactDoesNotExistException exception) { String message = String.format( - "Unknown contact with id '%d' given for school with id '%d'", + "Unknown contact with ID %d given for school with ID %d", exception.getContactId(), exception.getSchoolId()); end(ctx, message, 400); } @@ -194,23 +195,24 @@ public void handleBadImageRequest(RoutingContext ctx) { } public void handleS3FailedUpload(RoutingContext ctx, String exceptionMessage) { - String message = "The given file could not be uploaded to AWS S3: " + exceptionMessage; + String message = + "The given file could not be uploaded to AWS S3 with error: " + exceptionMessage; end(ctx, message, 502); } public void handleSchoolDoesNotExist(RoutingContext ctx, SchoolDoesNotExistException e) { - String message = String.format("No school found with given id: %d", e.getSchoolId()); + String message = String.format("No school found with ID %d", e.getSchoolId()); end(ctx, message, 400); } public void handleBookLogDoesNotExist(RoutingContext ctx, BookLogDoesNotExistException e) { - String message = String.format("No book log found with given id: %d", e.getBookId()); + String message = String.format("No book log found with ID %d", e.getBookId()); end(ctx, message, 400); } public void handleCsvSerializer(RoutingContext ctx, CsvSerializerException e) { String message = - String.format("Report with id: %d was unable to be converted to CSV", e.getReportId()); + String.format("Report with ID %d was unable to be converted to CSV", e.getReportId()); end(ctx, message, 500); } diff --git a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java new file mode 100644 index 00000000..e2966f0d --- /dev/null +++ b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java @@ -0,0 +1,63 @@ +package com.codeforcommunity.rest.subrouter.authenticated; + +import static com.codeforcommunity.rest.ApiRouter.end; + +import com.codeforcommunity.api.authenticated.IProtectedDataProcessor; +import com.codeforcommunity.auth.JWTData; +import com.codeforcommunity.dto.data.MetricsCountryResponse; +import com.codeforcommunity.dto.data.MetricsSchoolResponse; +import com.codeforcommunity.enums.Country; +import com.codeforcommunity.rest.IRouter; +import com.codeforcommunity.rest.RestFunctions; +import io.vertx.core.Vertx; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.Route; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; + +public class ProtectedDataRouter implements IRouter { + + private final IProtectedDataProcessor processor; + + public ProtectedDataRouter(IProtectedDataProcessor processor) { + this.processor = processor; + } + + @Override + public Router initializeRouter(Vertx vertx) { + Router router = Router.router(vertx); + + registerGetFixedCountryMetrics(router); + registerGetFixedSchoolyMetrics(router); + + return router; + } + + private void registerGetFixedCountryMetrics(Router router) { + Route getCountryMetricsRoute = router.get("/country/:country"); + getCountryMetricsRoute.handler(this::handleGetFixedCountryMetrics); + } + + private void registerGetFixedSchoolyMetrics(Router router) { + Route getSchoolMetricsRoute = router.get("/school/:school_id"); + getSchoolMetricsRoute.handler(this::handleGetFixedSchoolMetrics); + } + + private void handleGetFixedCountryMetrics(RoutingContext ctx) { + JWTData userData = ctx.get("jwt_data"); + + Country country = RestFunctions.getCountryFromString(ctx.pathParam("country")); + MetricsCountryResponse response = processor.getFixedCountryMetrics(userData, country); + + end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); + } + + private void handleGetFixedSchoolMetrics(RoutingContext ctx) { + JWTData userData = ctx.get("jwt_data"); + + int schoolId = RestFunctions.getPathParamAsInt(ctx, "school_id"); + MetricsSchoolResponse response = processor.getFixedSchoolMetrics(userData, schoolId); + + end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); + } +} diff --git a/service/src/main/java/com/codeforcommunity/ServiceMain.java b/service/src/main/java/com/codeforcommunity/ServiceMain.java index c917679c..acf094e2 100644 --- a/service/src/main/java/com/codeforcommunity/ServiceMain.java +++ b/service/src/main/java/com/codeforcommunity/ServiceMain.java @@ -1,6 +1,7 @@ package com.codeforcommunity; import com.codeforcommunity.api.authenticated.IProtectedCountryProcessor; +import com.codeforcommunity.api.authenticated.IProtectedDataProcessor; import com.codeforcommunity.api.authenticated.IProtectedSchoolProcessor; import com.codeforcommunity.api.authenticated.IProtectedUserProcessor; import com.codeforcommunity.api.unauthenticated.IAuthProcessor; @@ -9,6 +10,7 @@ import com.codeforcommunity.auth.JWTHandler; import com.codeforcommunity.logger.SLogger; import com.codeforcommunity.processor.authenticated.ProtectedCountryProcessorImpl; +import com.codeforcommunity.processor.authenticated.ProtectedDataProcessorImpl; import com.codeforcommunity.processor.authenticated.ProtectedSchoolProcessorImpl; import com.codeforcommunity.processor.authenticated.ProtectedUserProcessorImpl; import com.codeforcommunity.processor.unauthenticated.AuthProcessorImpl; @@ -89,11 +91,17 @@ private void initializeServer() { IProtectedUserProcessor protectedUserProc = new ProtectedUserProcessorImpl(this.db, emailer); IProtectedCountryProcessor protectedCountryProc = new ProtectedCountryProcessorImpl(this.db); IProtectedSchoolProcessor protectedSchoolProc = new ProtectedSchoolProcessorImpl(this.db); + IProtectedDataProcessor protectedDataProc = new ProtectedDataProcessorImpl(this.db); // Create the API router and start the HTTP server ApiRouter router = new ApiRouter( - jwtAuthorizer, authProc, protectedUserProc, protectedCountryProc, protectedSchoolProc); + jwtAuthorizer, + authProc, + protectedUserProc, + protectedCountryProc, + protectedSchoolProc, + protectedDataProc); startApiServer(router, vertx); } diff --git a/service/src/main/java/com/codeforcommunity/dataaccess/SchoolDatabaseOperations.java b/service/src/main/java/com/codeforcommunity/dataaccess/SchoolDatabaseOperations.java new file mode 100644 index 00000000..04cb4629 --- /dev/null +++ b/service/src/main/java/com/codeforcommunity/dataaccess/SchoolDatabaseOperations.java @@ -0,0 +1,69 @@ +package com.codeforcommunity.dataaccess; + +import static org.jooq.generated.Tables.SCHOOLS; +import static org.jooq.generated.Tables.SCHOOL_CONTACTS; +import static org.jooq.generated.Tables.SCHOOL_REPORTS_WITHOUT_LIBRARIES; +import static org.jooq.generated.Tables.SCHOOL_REPORTS_WITH_LIBRARIES; + +import com.codeforcommunity.dto.report.ReportGeneric; +import com.codeforcommunity.dto.report.ReportWithLibrary; +import com.codeforcommunity.dto.report.ReportWithoutLibrary; +import com.codeforcommunity.dto.school.SchoolContact; +import com.codeforcommunity.enums.LibraryStatus; +import java.util.List; +import org.jooq.DSLContext; +import org.jooq.generated.tables.records.SchoolsRecord; + +public class SchoolDatabaseOperations { + + private final DSLContext db; + + public SchoolDatabaseOperations(DSLContext db) { + this.db = db; + } + + public SchoolsRecord getSchool(int schoolId) { + return db.selectFrom(SCHOOLS) + .where(SCHOOLS.ID.eq(schoolId)) + .and(SCHOOLS.DELETED_AT.isNull()) + .fetchOne(); + } + + public List getSchoolContacts(int schoolId) { + return db.selectFrom(SCHOOL_CONTACTS) + .where(SCHOOL_CONTACTS.DELETED_AT.isNull()) + .and(SCHOOL_CONTACTS.SCHOOL_ID.eq(schoolId)) + .fetchInto(SchoolContact.class); + } + + public ReportGeneric getMostRecentReport(int schoolId) throws IllegalArgumentException { + SchoolsRecord school = this.getSchool(schoolId); + if (school == null) { + throw new IllegalArgumentException( + String.format("School with ID %d does not exist", schoolId)); + } + + ReportGeneric report = null; + LibraryStatus libraryStatus = school.getLibraryStatus(); + + if (libraryStatus == LibraryStatus.EXISTS) { + report = + db.selectFrom(SCHOOL_REPORTS_WITH_LIBRARIES) + .where(SCHOOL_REPORTS_WITH_LIBRARIES.DELETED_AT.isNull()) + .and(SCHOOL_REPORTS_WITH_LIBRARIES.SCHOOL_ID.eq(schoolId)) + .orderBy(SCHOOL_REPORTS_WITH_LIBRARIES.ID.desc()) + .limit(1) + .fetchOneInto(ReportWithLibrary.class); + } else if (libraryStatus == LibraryStatus.DOES_NOT_EXIST) { + report = + db.selectFrom(SCHOOL_REPORTS_WITHOUT_LIBRARIES) + .where(SCHOOL_REPORTS_WITHOUT_LIBRARIES.DELETED_AT.isNull()) + .and(SCHOOL_REPORTS_WITHOUT_LIBRARIES.SCHOOL_ID.eq(schoolId)) + .orderBy(SCHOOL_REPORTS_WITHOUT_LIBRARIES.ID.desc()) + .limit(1) + .fetchOneInto(ReportWithoutLibrary.class); + } + + return report; + } +} diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java new file mode 100644 index 00000000..2665d591 --- /dev/null +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java @@ -0,0 +1,102 @@ +package com.codeforcommunity.processor.authenticated; + +import static org.jooq.generated.Tables.SCHOOLS; +import static org.jooq.generated.Tables.USERS; + +import com.codeforcommunity.api.authenticated.IProtectedDataProcessor; +import com.codeforcommunity.auth.JWTData; +import com.codeforcommunity.dataaccess.SchoolDatabaseOperations; +import com.codeforcommunity.dto.data.MetricsCountryResponse; +import com.codeforcommunity.dto.data.MetricsSchoolResponse; +import com.codeforcommunity.dto.report.ReportGeneric; +import com.codeforcommunity.dto.report.ReportWithLibrary; +import com.codeforcommunity.enums.Country; +import com.codeforcommunity.enums.LibraryStatus; +import com.codeforcommunity.enums.PrivilegeLevel; +import com.codeforcommunity.exceptions.SchoolDoesNotExistException; +import org.jooq.DSLContext; + +public class ProtectedDataProcessorImpl implements IProtectedDataProcessor { + private final SchoolDatabaseOperations schoolDatabaseOperations; + private final DSLContext db; + + public ProtectedDataProcessorImpl(DSLContext db) { + this.schoolDatabaseOperations = new SchoolDatabaseOperations(db); + this.db = db; + } + + @Override + public MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country country) { + int countSchools = + db.fetchCount( + db.selectFrom(SCHOOLS) + .where(SCHOOLS.HIDDEN.isFalse()) + .and(SCHOOLS.DELETED_AT.isNull()) + .and(SCHOOLS.COUNTRY.eq(country))); + + int countVolunteerAccounts = + db.fetchCount( + db.selectFrom(USERS) + .where(USERS.DELETED_AT.isNull()) + .and(USERS.COUNTRY.eq(country)) + .and(USERS.PRIVILEGE_LEVEL.eq(PrivilegeLevel.STANDARD))); + + int countAdminAccounts = + db.fetchCount( + db.selectFrom(USERS) + .where(USERS.DELETED_AT.isNull()) + .and(USERS.COUNTRY.eq(country)) + .and(USERS.PRIVILEGE_LEVEL.eq(PrivilegeLevel.ADMIN))); + + Float avgCountBooksPerStudent = null; // TODO + Float avgCountStudentLibrariansPerSchool = null; // TODO + + int countSchoolsWithLibrary = + db.fetchCount( + db.selectFrom(SCHOOLS) + .where(SCHOOLS.HIDDEN.isFalse()) + .and(SCHOOLS.DELETED_AT.isNull()) + .and(SCHOOLS.COUNTRY.eq(country)) + .and(SCHOOLS.LIBRARY_STATUS.eq(LibraryStatus.EXISTS))); + + float percentSchoolsWithLibraries = + (countSchools > 0) ? ((float) countSchoolsWithLibrary / (float) countSchools) * 100 : 0; + + return new MetricsCountryResponse( + countSchools, + countVolunteerAccounts, + countAdminAccounts, + avgCountBooksPerStudent, + avgCountStudentLibrariansPerSchool, + percentSchoolsWithLibraries); + } + + @Override + public MetricsSchoolResponse getFixedSchoolMetrics(JWTData userData, int schoolId) { + ReportGeneric report; + + try { + report = schoolDatabaseOperations.getMostRecentReport(schoolId); + } catch (IllegalArgumentException e) { + throw new SchoolDoesNotExistException(schoolId); + } + + Integer countBooks = report.getNumberOfBooks(); + Integer countStudents = report.getNumberOfChildren(); + + Float countBooksPerStudent = + (countBooks != null && countStudents != null) + ? ((float) countBooks / (float) countStudents) + : null; + + Integer countStudentLibrarians = + (report instanceof ReportWithLibrary) + ? ((ReportWithLibrary) report).getNumberOfStudentLibrarians() + : null; + + Integer netBooksInOut = null; // TODO + + return new MetricsSchoolResponse( + countBooksPerStudent, countStudents, countStudentLibrarians, netBooksInOut); + } +} diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java index 9464385b..27865704 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java @@ -8,6 +8,7 @@ import com.codeforcommunity.api.authenticated.IProtectedSchoolProcessor; import com.codeforcommunity.auth.JWTData; +import com.codeforcommunity.dataaccess.SchoolDatabaseOperations; import com.codeforcommunity.dto.CsvSerializer; import com.codeforcommunity.dto.report.ReportGeneric; import com.codeforcommunity.dto.report.ReportGenericListResponse; @@ -54,9 +55,11 @@ public class ProtectedSchoolProcessorImpl implements IProtectedSchoolProcessor { private final SLogger logger = new SLogger(ProtectedSchoolProcessorImpl.class); + private final SchoolDatabaseOperations schoolDatabaseOperations; private final DSLContext db; public ProtectedSchoolProcessorImpl(DSLContext db) { + this.schoolDatabaseOperations = new SchoolDatabaseOperations(db); this.db = db; } @@ -84,7 +87,7 @@ public School getSchool(JWTData userData, int schoolId) { throw new SchoolDoesNotExistException(schoolId); } - List contacts = this.queryForSchoolContacts(schoolId); + List contacts = schoolDatabaseOperations.getSchoolContacts(schoolId); school.setContacts(contacts); return school; } @@ -151,7 +154,7 @@ public School createSchool(JWTData userData, UpsertSchoolRequest upsertSchoolReq school.store(); Integer schoolId = school.getId(); - List contacts = this.queryForSchoolContacts(schoolId); + List contacts = schoolDatabaseOperations.getSchoolContacts(schoolId); return new School( school.getId(), @@ -172,7 +175,7 @@ public School createSchool(JWTData userData, UpsertSchoolRequest upsertSchoolReq @Override public SchoolContactListResponse getAllSchoolContacts(JWTData userData, int schoolId) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -188,7 +191,7 @@ public SchoolContactListResponse getAllSchoolContacts(JWTData userData, int scho @Override public SchoolContact getSchoolContact(JWTData userData, int schoolId, int contactId) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -210,7 +213,7 @@ public SchoolContact getSchoolContact(JWTData userData, int schoolId, int contac @Override public SchoolContact createSchoolContact( JWTData userData, int schoolId, UpsertSchoolContactRequest upsertSchoolContactRequest) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -328,7 +331,7 @@ public void deleteSchoolContact(JWTData userData, int schoolId, int contactId) { @Override public void updateSchool( JWTData userData, int schoolId, UpsertSchoolRequest upsertSchoolRequest) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -361,7 +364,7 @@ public void deleteSchool(JWTData userData, int schoolId) { throw new AdminOnlyRouteException(); } - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -372,7 +375,7 @@ public void deleteSchool(JWTData userData, int schoolId) { @Override public void hideSchool(JWTData userData, int schoolId) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -382,7 +385,7 @@ public void hideSchool(JWTData userData, int schoolId) { @Override public void unHideSchool(JWTData userData, int schoolId) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -394,7 +397,7 @@ public void unHideSchool(JWTData userData, int schoolId) { @Override public ReportWithLibrary createReportWithLibrary( JWTData userData, int schoolId, UpsertReportWithLibrary req) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -461,7 +464,7 @@ public ReportWithLibrary createReportWithLibrary( @Override public void updateReportWithLibrary( JWTData userData, int schoolId, int reportId, UpsertReportWithLibrary req) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -507,30 +510,12 @@ public void updateReportWithLibrary( @Override public ReportGeneric getMostRecentReport(JWTData userData, int schoolId) { - SchoolsRecord school = this.queryForSchool(schoolId); - if (school == null) { - throw new SchoolDoesNotExistException(schoolId); - } - - ReportGeneric report = null; - LibraryStatus libraryStatus = school.getLibraryStatus(); + ReportGeneric report; - if (libraryStatus == LibraryStatus.EXISTS) { - report = - db.selectFrom(SCHOOL_REPORTS_WITH_LIBRARIES) - .where(SCHOOL_REPORTS_WITH_LIBRARIES.DELETED_AT.isNull()) - .and(SCHOOL_REPORTS_WITH_LIBRARIES.SCHOOL_ID.eq(schoolId)) - .orderBy(SCHOOL_REPORTS_WITH_LIBRARIES.ID.desc()) - .limit(1) - .fetchOneInto(ReportWithLibrary.class); - } else if (libraryStatus == LibraryStatus.DOES_NOT_EXIST) { - report = - db.selectFrom(SCHOOL_REPORTS_WITHOUT_LIBRARIES) - .where(SCHOOL_REPORTS_WITHOUT_LIBRARIES.DELETED_AT.isNull()) - .and(SCHOOL_REPORTS_WITHOUT_LIBRARIES.SCHOOL_ID.eq(schoolId)) - .orderBy(SCHOOL_REPORTS_WITHOUT_LIBRARIES.ID.desc()) - .limit(1) - .fetchOneInto(ReportWithoutLibrary.class); + try { + report = schoolDatabaseOperations.getMostRecentReport(schoolId); + } catch (IllegalArgumentException e) { + throw new SchoolDoesNotExistException(schoolId); } if (report == null) { @@ -544,7 +529,7 @@ public ReportGeneric getMostRecentReport(JWTData userData, int schoolId) { @Override public ReportWithoutLibrary createReportWithoutLibrary( JWTData userData, int schoolId, UpsertReportWithoutLibrary req) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -594,7 +579,7 @@ public ReportWithoutLibrary createReportWithoutLibrary( public void updateReportWithoutLibrary( JWTData userData, int schoolId, int reportId, UpsertReportWithoutLibrary req) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -636,7 +621,7 @@ public ReportGenericListResponse getPaginatedReports(JWTData userData, int schoo throw new MalformedParameterException("p"); } - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -686,7 +671,7 @@ public BookLog createBookLog(JWTData userData, int schoolId, UpsertBookLogReques throw new AdminOnlyRouteException(); } - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -711,7 +696,7 @@ public BookLog updateBookLog( if (!userData.isAdmin()) { throw new AdminOnlyRouteException(); } - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -736,7 +721,7 @@ public BookLog updateBookLog( @Override public BookLogListResponse getBookLog(JWTData userData, int schoolId) { - SchoolsRecord school = this.queryForSchool(schoolId); + SchoolsRecord school = schoolDatabaseOperations.getSchool(schoolId); if (school == null) { throw new SchoolDoesNotExistException(schoolId); } @@ -775,18 +760,4 @@ public String getReportAsCsv(JWTData userData, int reportId, boolean hasLibrary) return builder.toString(); } - - private SchoolsRecord queryForSchool(int schoolId) { - return db.selectFrom(SCHOOLS) - .where(SCHOOLS.ID.eq(schoolId)) - .and(SCHOOLS.DELETED_AT.isNull()) - .fetchOne(); - } - - private List queryForSchoolContacts(int schoolId) { - return db.selectFrom(SCHOOL_CONTACTS) - .where(SCHOOL_CONTACTS.DELETED_AT.isNull()) - .and(SCHOOL_CONTACTS.SCHOOL_ID.eq(schoolId)) - .fetchInto(SchoolContact.class); - } } From a4fa14223de0fe03a1d00949ddeb265d60259911 Mon Sep 17 00:00:00 2001 From: Justin Konecny Date: Mon, 21 Jun 2021 22:47:19 -0400 Subject: [PATCH 2/8] Add country level averages --- .../codeforcommunity/dto/school/School.java | 1 - .../ProtectedDataProcessorImpl.java | 108 +++++++++++++++++- .../ProtectedSchoolProcessorImpl.java | 23 ++-- 3 files changed, 117 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/com/codeforcommunity/dto/school/School.java b/api/src/main/java/com/codeforcommunity/dto/school/School.java index 67b2f747..45e1a135 100644 --- a/api/src/main/java/com/codeforcommunity/dto/school/School.java +++ b/api/src/main/java/com/codeforcommunity/dto/school/School.java @@ -2,7 +2,6 @@ import com.codeforcommunity.enums.Country; import com.codeforcommunity.enums.LibraryStatus; -import java.util.ArrayList; import java.util.List; public class School { diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java index 2665d591..fe6238ae 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java @@ -14,9 +14,13 @@ import com.codeforcommunity.enums.LibraryStatus; import com.codeforcommunity.enums.PrivilegeLevel; import com.codeforcommunity.exceptions.SchoolDoesNotExistException; +import com.codeforcommunity.logger.SLogger; +import java.util.ArrayList; +import java.util.List; import org.jooq.DSLContext; public class ProtectedDataProcessorImpl implements IProtectedDataProcessor { + private final SLogger logger = new SLogger(ProtectedDataProcessorImpl.class); private final SchoolDatabaseOperations schoolDatabaseOperations; private final DSLContext db; @@ -48,8 +52,11 @@ public MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country c .and(USERS.COUNTRY.eq(country)) .and(USERS.PRIVILEGE_LEVEL.eq(PrivilegeLevel.ADMIN))); - Float avgCountBooksPerStudent = null; // TODO - Float avgCountStudentLibrariansPerSchool = null; // TODO + List schoolReports = this.getCountryReports(country); + + Float avgCountBooksPerStudent = this.getCountryBooksPerStudentAverage(country, schoolReports); + Float avgCountStudentLibrariansPerSchool = + this.getCountryStudentLibrariansPerSchoolAverage(country, schoolReports); int countSchoolsWithLibrary = db.fetchCount( @@ -99,4 +106,101 @@ public MetricsSchoolResponse getFixedSchoolMetrics(JWTData userData, int schoolI return new MetricsSchoolResponse( countBooksPerStudent, countStudents, countStudentLibrarians, netBooksInOut); } + + private List getCountryReports(Country country) { + // Get all schools for this country that are not deleted or hidden + List schoolIds = + db.selectFrom(SCHOOLS) + .where(SCHOOLS.DELETED_AT.isNull()) + .and(SCHOOLS.HIDDEN.isFalse()) + .and(SCHOOLS.COUNTRY.eq(country)) + .fetch(SCHOOLS.ID); + + List reports = new ArrayList(); + + for (int schoolId : schoolIds) { + // For each school, get the most recent report + ReportGeneric report = schoolDatabaseOperations.getMostRecentReport(schoolId); + + if (report == null) { + logger.info( + String.format( + "No report found for school with ID `%d` in country `%s`", + schoolId, country.getName())); + continue; + } + + reports.add(report); + } + + return reports; + } + + private Float getCountryBooksPerStudentAverage( + Country country, List schoolReports) { + List schoolAveragesBooksPerStudent = new ArrayList(); + + for (ReportGeneric report : schoolReports) { + // For each report, calculate books per student + Integer countBooks = report.getNumberOfBooks(); + Integer countStudents = report.getNumberOfChildren(); + + if (countBooks == null || countStudents == null) { + logger.info( + String.format( + "School report with ID `%d` missing count books or count students", + report.getId())); + continue; + } + + float schoolAvg = ((float) countBooks) / ((float) countStudents); + schoolAveragesBooksPerStudent.add(schoolAvg); + } + + if (schoolAveragesBooksPerStudent.isEmpty()) { + return null; + } + + return (float) schoolAveragesBooksPerStudent.stream().mapToDouble(d -> d).average().orElse(0.0); + } + + private Float getCountryStudentLibrariansPerSchoolAverage( + Country country, List schoolReports) { + int totalCountStudentLibrarians = 0; + int totalCountSchoolsWithLibraries = 0; // TODO: SHOULD THIS BE ALL SCHOOLS + + for (ReportGeneric report : schoolReports) { + // For each report, get count student librarians + if (report.getLibraryStatus() != LibraryStatus.EXISTS + || !(report instanceof ReportWithLibrary)) { + // Skip reports with no libraries + + logger.info( + String.format( + "Skipping school report with ID `%d` since it has no library", report.getId())); + continue; + } + + ReportWithLibrary reportWithLibrary = (ReportWithLibrary) report; + + Integer numStudentLibrarians = reportWithLibrary.getNumberOfStudentLibrarians(); + if (numStudentLibrarians == null) { + logger.info( + String.format( + "Skipping school report with ID `%d` since it has a `null` student librarian count", + report.getId())); + continue; + } + + // Otherwise, increment count of schools and add the number of librarians + totalCountStudentLibrarians += numStudentLibrarians; + totalCountSchoolsWithLibraries++; + } + + if (totalCountSchoolsWithLibraries == 0) { + return null; + } + + return (float) totalCountStudentLibrarians / (float) totalCountSchoolsWithLibraries; + } } diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java index b9af2cd8..05299d00 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java @@ -1,5 +1,11 @@ package com.codeforcommunity.processor.authenticated; +import static org.jooq.generated.Tables.BOOK_LOGS; +import static org.jooq.generated.Tables.SCHOOLS; +import static org.jooq.generated.Tables.SCHOOL_CONTACTS; +import static org.jooq.generated.Tables.SCHOOL_REPORTS_WITHOUT_LIBRARIES; +import static org.jooq.generated.Tables.SCHOOL_REPORTS_WITH_LIBRARIES; + import com.codeforcommunity.api.authenticated.IProtectedSchoolProcessor; import com.codeforcommunity.auth.JWTData; import com.codeforcommunity.dataaccess.SchoolDatabaseOperations; @@ -34,6 +40,11 @@ import com.codeforcommunity.exceptions.SchoolContactDoesNotExistException; import com.codeforcommunity.exceptions.SchoolDoesNotExistException; import com.codeforcommunity.logger.SLogger; +import java.sql.Timestamp; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; import org.jooq.DSLContext; import org.jooq.generated.tables.records.BookLogsRecord; import org.jooq.generated.tables.records.SchoolContactsRecord; @@ -41,18 +52,6 @@ import org.jooq.generated.tables.records.SchoolReportsWithoutLibrariesRecord; import org.jooq.generated.tables.records.SchoolsRecord; -import java.sql.Timestamp; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -import static org.jooq.generated.Tables.BOOK_LOGS; -import static org.jooq.generated.Tables.SCHOOLS; -import static org.jooq.generated.Tables.SCHOOL_CONTACTS; -import static org.jooq.generated.Tables.SCHOOL_REPORTS_WITHOUT_LIBRARIES; -import static org.jooq.generated.Tables.SCHOOL_REPORTS_WITH_LIBRARIES; - public class ProtectedSchoolProcessorImpl implements IProtectedSchoolProcessor { private final SLogger logger = new SLogger(ProtectedSchoolProcessorImpl.class); From ecee2b330cbc571a4ed99af293f4a45615693f95 Mon Sep 17 00:00:00 2001 From: Max Sebso Date: Thu, 23 Dec 2021 21:10:56 -0800 Subject: [PATCH 3/8] added total metric --- .../dto/data/MetricsTotalResponse.java | 30 +++++++++++++++++++ .../authenticated/ProtectedDataRouter.java | 14 +++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java diff --git a/api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java b/api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java new file mode 100644 index 00000000..cedba736 --- /dev/null +++ b/api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java @@ -0,0 +1,30 @@ +package com.codeforcommunity.dto.data; + +public class MetricsTotalResponse { + private Integer countSchools; + private Integer countBooks; + + public MetricsTotalResponse( + Integer countSchools, + Integer countBooks + ) { + this.countSchools = countSchools; + this.countBooks = countBooks; + } + + public Integer getCountSchools() { + return countSchools; + } + + public void setCountSchools(Integer countSchools) { + this.countSchools = countSchools; + } + + public Integer getCountBooks() { + return countBooks; + } + + public void setCountBooks(Integer countBooks) { + this.countBooks = countBooks; + } +} diff --git a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java index e2966f0d..dcbae836 100644 --- a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java +++ b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java @@ -27,18 +27,24 @@ public ProtectedDataRouter(IProtectedDataProcessor processor) { public Router initializeRouter(Vertx vertx) { Router router = Router.router(vertx); + registerGetFixedTotalMetrics(router); registerGetFixedCountryMetrics(router); - registerGetFixedSchoolyMetrics(router); + registerGetFixedSchoolMetrics(router); return router; } + private void registerGetFixedTotalMetrics(Router router) { + Route getTotalMetricRoute = router.get("/total"); + getTotalMetricRoute.handler(this::handleGetFixedTotalMetrics); + } + private void registerGetFixedCountryMetrics(Router router) { Route getCountryMetricsRoute = router.get("/country/:country"); getCountryMetricsRoute.handler(this::handleGetFixedCountryMetrics); } - private void registerGetFixedSchoolyMetrics(Router router) { + private void registerGetFixedSchoolMetrics(Router router) { Route getSchoolMetricsRoute = router.get("/school/:school_id"); getSchoolMetricsRoute.handler(this::handleGetFixedSchoolMetrics); } @@ -52,6 +58,10 @@ private void handleGetFixedCountryMetrics(RoutingContext ctx) { end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); } + private void handleGetFixedTotalMetrics(RoutingContext ctx) { + return; + } + private void handleGetFixedSchoolMetrics(RoutingContext ctx) { JWTData userData = ctx.get("jwt_data"); From 0b37b20364689a0b04286de8d902d74768f69514 Mon Sep 17 00:00:00 2001 From: Max Sebso Date: Sat, 25 Dec 2021 13:06:11 -0800 Subject: [PATCH 4/8] added proc impl --- .../api/authenticated/IProtectedDataProcessor.java | 3 +++ .../authenticated/ProtectedDataRouter.java | 14 ++++++++++---- .../authenticated/ProtectedDataProcessorImpl.java | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java index 5e240d82..9624309c 100644 --- a/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java +++ b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedDataProcessor.java @@ -3,10 +3,13 @@ import com.codeforcommunity.auth.JWTData; import com.codeforcommunity.dto.data.MetricsCountryResponse; import com.codeforcommunity.dto.data.MetricsSchoolResponse; +import com.codeforcommunity.dto.data.MetricsTotalResponse; import com.codeforcommunity.enums.Country; public interface IProtectedDataProcessor { + MetricsTotalResponse getFixedTotalMetrics(JWTData userData); + MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country country); MetricsSchoolResponse getFixedSchoolMetrics(JWTData userData, int schoolId); diff --git a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java index dcbae836..708e6d0a 100644 --- a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java +++ b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java @@ -6,10 +6,12 @@ import com.codeforcommunity.auth.JWTData; import com.codeforcommunity.dto.data.MetricsCountryResponse; import com.codeforcommunity.dto.data.MetricsSchoolResponse; +import com.codeforcommunity.dto.data.MetricsTotalResponse; import com.codeforcommunity.enums.Country; import com.codeforcommunity.rest.IRouter; import com.codeforcommunity.rest.RestFunctions; import io.vertx.core.Vertx; +import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.Route; import io.vertx.ext.web.Router; @@ -49,6 +51,14 @@ private void registerGetFixedSchoolMetrics(Router router) { getSchoolMetricsRoute.handler(this::handleGetFixedSchoolMetrics); } + private void handleGetFixedTotalMetrics(RoutingContext ctx) { + JWTData userData = ctx.get("jwt_data"); + + MetricsTotalResponse response = processor.getFixedTotalMetrics(userData); + + end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); + } + private void handleGetFixedCountryMetrics(RoutingContext ctx) { JWTData userData = ctx.get("jwt_data"); @@ -58,10 +68,6 @@ private void handleGetFixedCountryMetrics(RoutingContext ctx) { end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); } - private void handleGetFixedTotalMetrics(RoutingContext ctx) { - return; - } - private void handleGetFixedSchoolMetrics(RoutingContext ctx) { JWTData userData = ctx.get("jwt_data"); diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java index fe6238ae..ba364fc6 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java @@ -8,6 +8,7 @@ import com.codeforcommunity.dataaccess.SchoolDatabaseOperations; import com.codeforcommunity.dto.data.MetricsCountryResponse; import com.codeforcommunity.dto.data.MetricsSchoolResponse; +import com.codeforcommunity.dto.data.MetricsTotalResponse; import com.codeforcommunity.dto.report.ReportGeneric; import com.codeforcommunity.dto.report.ReportWithLibrary; import com.codeforcommunity.enums.Country; @@ -29,6 +30,19 @@ public ProtectedDataProcessorImpl(DSLContext db) { this.db = db; } + @Override + public MetricsTotalResponse getFixedTotalMetrics(JWTData userData) { + int countSchools = + db.fetchCount( + db.selectFrom(SCHOOLS) + .where(SCHOOLS.HIDDEN.isFalse()) + .and(SCHOOLS.DELETED_AT.isNull())); + + int countBooks = 0; + + return new MetricsTotalResponse(countSchools,countBooks); + } + @Override public MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country country) { int countSchools = From a23b01a096fdac60af40eff2031624dcea588bea Mon Sep 17 00:00:00 2001 From: Max Sebso Date: Sat, 25 Dec 2021 19:48:06 -0800 Subject: [PATCH 5/8] added country filter route for schools --- .../authenticated/IProtectedSchoolProcessor.java | 3 +++ .../authenticated/ProtectedSchoolRouter.java | 14 ++++++++++++++ .../ProtectedSchoolProcessorImpl.java | 12 ++++++++++++ 3 files changed, 29 insertions(+) diff --git a/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java index 3c0b465e..bc737dc2 100644 --- a/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java +++ b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java @@ -16,11 +16,14 @@ import com.codeforcommunity.dto.school.UpsertBookLogRequest; import com.codeforcommunity.dto.school.UpsertSchoolContactRequest; import com.codeforcommunity.dto.school.UpsertSchoolRequest; +import com.codeforcommunity.enums.Country; public interface IProtectedSchoolProcessor { SchoolListResponse getAllSchools(JWTData userData); + SchoolListResponse getAllSchoolsCountryFilter(JWTData userData, Country country); + School getSchool(JWTData userData, int schoolId); SchoolContactListResponse getAllSchoolContacts(JWTData userData, int schoolId); diff --git a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java index 7ff4a418..c81f4195 100644 --- a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java +++ b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java @@ -19,6 +19,7 @@ import com.codeforcommunity.dto.school.UpsertBookLogRequest; import com.codeforcommunity.dto.school.UpsertSchoolContactRequest; import com.codeforcommunity.dto.school.UpsertSchoolRequest; +import com.codeforcommunity.enums.Country; import com.codeforcommunity.rest.IRouter; import com.codeforcommunity.rest.RestFunctions; import io.vertx.core.Vertx; @@ -41,6 +42,7 @@ public Router initializeRouter(Vertx vertx) { // Register all school routes registerGetAllSchools(router); + registerGetAllSchoolsCountryFilter(router); registerGetSchool(router); registerCreateSchool(router); registerUpdateSchool(router); @@ -79,6 +81,11 @@ private void registerGetAllSchools(Router router) { getSchoolsRoute.handler(this::handleGetAllSchoolsRoute); } + private void registerGetAllSchoolsCountryFilter(Router router) { + Route getSchoolsRoute = router.get("/:country"); + getSchoolsRoute.handler(this::handleGetAllSchoolsCountryFilterRoute); + } + private void registerGetSchool(Router router) { Route getSchoolsRoute = router.get("/:school_id"); getSchoolsRoute.handler(this::handleGetSchoolRoute); @@ -200,6 +207,13 @@ private void handleGetAllSchoolsRoute(RoutingContext ctx) { end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); } + private void handleGetAllSchoolsCountryFilterRoute(RoutingContext ctx) { + JWTData userData = ctx.get("jwt_data"); + Country country = RestFunctions.getCountryFromString(ctx.pathParam("country")); + SchoolListResponse response = processor.getAllSchoolsCountryFilter(userData, country); + end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); + } + private void handleGetSchoolRoute(RoutingContext ctx) { JWTData userData = ctx.get("jwt_data"); int schoolId = RestFunctions.getPathParamAsInt(ctx, "school_id"); diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java index 05299d00..3701f79c 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java @@ -74,6 +74,18 @@ public SchoolListResponse getAllSchools(JWTData userData) { return new SchoolListResponse(schools); } + @Override + public SchoolListResponse getAllSchoolsCountryFilter(JWTData userData, Country country) { + List schools = + db.selectFrom(SCHOOLS) + .where(SCHOOLS.HIDDEN.isFalse()) + .and(SCHOOLS.DELETED_AT.isNull()) + .and(SCHOOLS.COUNTRY.eq(country)) + .fetchInto(SchoolSummary.class); + + return new SchoolListResponse(schools); + } + @Override public School getSchool(JWTData userData, int schoolId) { School school = From 7bd8d791b8d77ff97c20f48736155d60df8df163 Mon Sep 17 00:00:00 2001 From: Max Sebso Date: Sat, 25 Dec 2021 22:38:02 -0800 Subject: [PATCH 6/8] route was a duplicate --- .../authenticated/IProtectedSchoolProcessor.java | 3 --- .../authenticated/ProtectedSchoolRouter.java | 13 ------------- .../authenticated/ProtectedSchoolProcessorImpl.java | 12 ------------ 3 files changed, 28 deletions(-) diff --git a/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java index bc737dc2..3c0b465e 100644 --- a/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java +++ b/api/src/main/java/com/codeforcommunity/api/authenticated/IProtectedSchoolProcessor.java @@ -16,14 +16,11 @@ import com.codeforcommunity.dto.school.UpsertBookLogRequest; import com.codeforcommunity.dto.school.UpsertSchoolContactRequest; import com.codeforcommunity.dto.school.UpsertSchoolRequest; -import com.codeforcommunity.enums.Country; public interface IProtectedSchoolProcessor { SchoolListResponse getAllSchools(JWTData userData); - SchoolListResponse getAllSchoolsCountryFilter(JWTData userData, Country country); - School getSchool(JWTData userData, int schoolId); SchoolContactListResponse getAllSchoolContacts(JWTData userData, int schoolId); diff --git a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java index c81f4195..d852d9ab 100644 --- a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java +++ b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java @@ -42,7 +42,6 @@ public Router initializeRouter(Vertx vertx) { // Register all school routes registerGetAllSchools(router); - registerGetAllSchoolsCountryFilter(router); registerGetSchool(router); registerCreateSchool(router); registerUpdateSchool(router); @@ -81,11 +80,6 @@ private void registerGetAllSchools(Router router) { getSchoolsRoute.handler(this::handleGetAllSchoolsRoute); } - private void registerGetAllSchoolsCountryFilter(Router router) { - Route getSchoolsRoute = router.get("/:country"); - getSchoolsRoute.handler(this::handleGetAllSchoolsCountryFilterRoute); - } - private void registerGetSchool(Router router) { Route getSchoolsRoute = router.get("/:school_id"); getSchoolsRoute.handler(this::handleGetSchoolRoute); @@ -207,13 +201,6 @@ private void handleGetAllSchoolsRoute(RoutingContext ctx) { end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); } - private void handleGetAllSchoolsCountryFilterRoute(RoutingContext ctx) { - JWTData userData = ctx.get("jwt_data"); - Country country = RestFunctions.getCountryFromString(ctx.pathParam("country")); - SchoolListResponse response = processor.getAllSchoolsCountryFilter(userData, country); - end(ctx.response(), 200, JsonObject.mapFrom(response).toString()); - } - private void handleGetSchoolRoute(RoutingContext ctx) { JWTData userData = ctx.get("jwt_data"); int schoolId = RestFunctions.getPathParamAsInt(ctx, "school_id"); diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java index 3701f79c..05299d00 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedSchoolProcessorImpl.java @@ -74,18 +74,6 @@ public SchoolListResponse getAllSchools(JWTData userData) { return new SchoolListResponse(schools); } - @Override - public SchoolListResponse getAllSchoolsCountryFilter(JWTData userData, Country country) { - List schools = - db.selectFrom(SCHOOLS) - .where(SCHOOLS.HIDDEN.isFalse()) - .and(SCHOOLS.DELETED_AT.isNull()) - .and(SCHOOLS.COUNTRY.eq(country)) - .fetchInto(SchoolSummary.class); - - return new SchoolListResponse(schools); - } - @Override public School getSchool(JWTData userData, int schoolId) { School school = From c0cac8935219cd81401ef125aed189f53b728607 Mon Sep 17 00:00:00 2001 From: Max Sebso Date: Sun, 2 Jan 2022 17:36:10 -0800 Subject: [PATCH 7/8] update --- .../dto/data/MetricGeneric.java | 28 +++++++++++++ .../dto/data/MetricsCountryResponse.java | 24 ++++++++++- .../dto/data/MetricsSchoolResponse.java | 13 +++++- .../dto/data/MetricsTotalResponse.java | 13 ++++-- .../authenticated/ProtectedDataRouter.java | 1 - .../authenticated/ProtectedSchoolRouter.java | 1 - .../ProtectedDataProcessorImpl.java | 42 ++++++++++++++++--- 7 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 api/src/main/java/com/codeforcommunity/dto/data/MetricGeneric.java diff --git a/api/src/main/java/com/codeforcommunity/dto/data/MetricGeneric.java b/api/src/main/java/com/codeforcommunity/dto/data/MetricGeneric.java new file mode 100644 index 00000000..71544291 --- /dev/null +++ b/api/src/main/java/com/codeforcommunity/dto/data/MetricGeneric.java @@ -0,0 +1,28 @@ +package com.codeforcommunity.dto.data; + +public class MetricGeneric { + + private Integer totalBooks; + private Integer totalStudents; + + public MetricGeneric(Integer totalBooks, Integer totalStudents) { + this.totalBooks = totalBooks; + this.totalStudents = totalStudents; + } + + public Integer getTotalBooks() { + return totalBooks; + } + + public Integer getTotalStudents() { + return totalStudents; + } + + public void setTotalBooks(Integer totalBooks) { + this.totalBooks = totalBooks; + } + + public void setTotalStudents(Integer totalStudents) { + this.totalStudents = totalStudents; + } +} diff --git a/api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java b/api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java index f0cd77bd..9acd2c53 100644 --- a/api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java +++ b/api/src/main/java/com/codeforcommunity/dto/data/MetricsCountryResponse.java @@ -7,6 +7,8 @@ public class MetricsCountryResponse { private Float avgCountBooksPerStudent; private Float avgCountStudentLibrariansPerSchool; private Float percentSchoolsWithLibraries; + private Integer countStudents; + private Integer countBooks; public MetricsCountryResponse( Integer countSchools, @@ -14,13 +16,17 @@ public MetricsCountryResponse( Integer countAdminAccounts, Float avgCountBooksPerStudent, Float avgCountStudentLibrariansPerSchool, - Float percentSchoolsWithLibraries) { + Float percentSchoolsWithLibraries, + Integer countStudents, + Integer countBooks) { this.countSchools = countSchools; this.countVolunteerAccounts = countVolunteerAccounts; this.countAdminAccounts = countAdminAccounts; this.avgCountBooksPerStudent = avgCountBooksPerStudent; this.avgCountStudentLibrariansPerSchool = avgCountStudentLibrariansPerSchool; this.percentSchoolsWithLibraries = percentSchoolsWithLibraries; + this.countStudents = countStudents; + this.countBooks = countBooks; } public Integer getCountSchools() { @@ -70,4 +76,20 @@ public Float getPercentSchoolsWithLibraries() { public void setPercentSchoolsWithLibraries(Float percentSchoolsWithLibraries) { this.percentSchoolsWithLibraries = percentSchoolsWithLibraries; } + + public Integer getCountBooks() { + return countBooks; + } + + public void setCountBooks(Integer countBooks) { + this.countBooks = countBooks; + } + + public Integer getCountStudents() { + return countStudents; + } + + public void setCountStudents(Integer countStudents) { + this.countStudents = countStudents; + } } diff --git a/api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java b/api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java index 50dda300..5e1956bc 100644 --- a/api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java +++ b/api/src/main/java/com/codeforcommunity/dto/data/MetricsSchoolResponse.java @@ -5,16 +5,19 @@ public class MetricsSchoolResponse { private Integer countStudents; private Integer countStudentLibrarians; private Integer netBooksInOut; + private Integer countBooks; public MetricsSchoolResponse( Float countBooksPerStudent, Integer countStudents, Integer countStudentLibrarians, - Integer netBooksInOut) { + Integer netBooksInOut, + Integer countBooks) { this.countBooksPerStudent = countBooksPerStudent; this.countStudents = countStudents; this.countStudentLibrarians = countStudentLibrarians; this.netBooksInOut = netBooksInOut; + this.countBooks = countBooks; } public Float getCountBooksPerStudent() { @@ -48,4 +51,12 @@ public Integer getNetBooksInOut() { public void setNetBooksInOut(Integer netBooksInOut) { this.netBooksInOut = netBooksInOut; } + + public Integer getCountBooks() { + return countBooks; + } + + public void setCountBooks(Integer countBooks) { + this.countBooks = countBooks; + } } diff --git a/api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java b/api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java index cedba736..f91bbe12 100644 --- a/api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java +++ b/api/src/main/java/com/codeforcommunity/dto/data/MetricsTotalResponse.java @@ -3,13 +3,12 @@ public class MetricsTotalResponse { private Integer countSchools; private Integer countBooks; + private Integer countStudents; - public MetricsTotalResponse( - Integer countSchools, - Integer countBooks - ) { + public MetricsTotalResponse(Integer countSchools, Integer countBooks, Integer countStudents) { this.countSchools = countSchools; this.countBooks = countBooks; + this.countStudents = countStudents; } public Integer getCountSchools() { @@ -27,4 +26,10 @@ public Integer getCountBooks() { public void setCountBooks(Integer countBooks) { this.countBooks = countBooks; } + + public Integer getCountStudents() { return countStudents; } + + public void setCountStudents(Integer countStudents) { + this.countStudents = countStudents; + } } diff --git a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java index 708e6d0a..123a34a8 100644 --- a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java +++ b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedDataRouter.java @@ -11,7 +11,6 @@ import com.codeforcommunity.rest.IRouter; import com.codeforcommunity.rest.RestFunctions; import io.vertx.core.Vertx; -import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.Route; import io.vertx.ext.web.Router; diff --git a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java index d852d9ab..7ff4a418 100644 --- a/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java +++ b/api/src/main/java/com/codeforcommunity/rest/subrouter/authenticated/ProtectedSchoolRouter.java @@ -19,7 +19,6 @@ import com.codeforcommunity.dto.school.UpsertBookLogRequest; import com.codeforcommunity.dto.school.UpsertSchoolContactRequest; import com.codeforcommunity.dto.school.UpsertSchoolRequest; -import com.codeforcommunity.enums.Country; import com.codeforcommunity.rest.IRouter; import com.codeforcommunity.rest.RestFunctions; import io.vertx.core.Vertx; diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java index ba364fc6..32620788 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java @@ -6,11 +6,13 @@ import com.codeforcommunity.api.authenticated.IProtectedDataProcessor; import com.codeforcommunity.auth.JWTData; import com.codeforcommunity.dataaccess.SchoolDatabaseOperations; +import com.codeforcommunity.dto.data.MetricGeneric; import com.codeforcommunity.dto.data.MetricsCountryResponse; import com.codeforcommunity.dto.data.MetricsSchoolResponse; import com.codeforcommunity.dto.data.MetricsTotalResponse; import com.codeforcommunity.dto.report.ReportGeneric; import com.codeforcommunity.dto.report.ReportWithLibrary; +import com.codeforcommunity.dto.school.SchoolSummary; import com.codeforcommunity.enums.Country; import com.codeforcommunity.enums.LibraryStatus; import com.codeforcommunity.enums.PrivilegeLevel; @@ -21,6 +23,7 @@ import org.jooq.DSLContext; public class ProtectedDataProcessorImpl implements IProtectedDataProcessor { + private final SLogger logger = new SLogger(ProtectedDataProcessorImpl.class); private final SchoolDatabaseOperations schoolDatabaseOperations; private final DSLContext db; @@ -38,9 +41,16 @@ public MetricsTotalResponse getFixedTotalMetrics(JWTData userData) { .where(SCHOOLS.HIDDEN.isFalse()) .and(SCHOOLS.DELETED_AT.isNull())); - int countBooks = 0; + List schoolIds = + db.selectFrom(SCHOOLS) + .where(SCHOOLS.HIDDEN.isFalse()) + .and(SCHOOLS.DELETED_AT.isNull()) + .fetch(SCHOOLS.ID); + + MetricGeneric metricGeneric = getGenericMetrics(getReports(schoolIds)); - return new MetricsTotalResponse(countSchools,countBooks); + return new MetricsTotalResponse(countSchools, metricGeneric.getTotalBooks(), + metricGeneric.getTotalStudents()); } @Override @@ -83,13 +93,17 @@ public MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country c float percentSchoolsWithLibraries = (countSchools > 0) ? ((float) countSchoolsWithLibrary / (float) countSchools) * 100 : 0; + MetricGeneric metricGeneric = getGenericMetrics(schoolReports); + return new MetricsCountryResponse( countSchools, countVolunteerAccounts, countAdminAccounts, avgCountBooksPerStudent, avgCountStudentLibrariansPerSchool, - percentSchoolsWithLibraries); + percentSchoolsWithLibraries, + metricGeneric.getTotalStudents(), + metricGeneric.getTotalBooks()); } @Override @@ -118,7 +132,7 @@ public MetricsSchoolResponse getFixedSchoolMetrics(JWTData userData, int schoolI Integer netBooksInOut = null; // TODO return new MetricsSchoolResponse( - countBooksPerStudent, countStudents, countStudentLibrarians, netBooksInOut); + countBooksPerStudent, countStudents, countStudentLibrarians, netBooksInOut, countBooks); } private List getCountryReports(Country country) { @@ -130,6 +144,10 @@ private List getCountryReports(Country country) { .and(SCHOOLS.COUNTRY.eq(country)) .fetch(SCHOOLS.ID); + return getReports(schoolIds); + } + + private List getReports(List schoolIds) { List reports = new ArrayList(); for (int schoolId : schoolIds) { @@ -139,8 +157,8 @@ private List getCountryReports(Country country) { if (report == null) { logger.info( String.format( - "No report found for school with ID `%d` in country `%s`", - schoolId, country.getName())); + "No report found for school with ID `%d`", + schoolId)); continue; } @@ -178,6 +196,18 @@ private Float getCountryBooksPerStudentAverage( return (float) schoolAveragesBooksPerStudent.stream().mapToDouble(d -> d).average().orElse(0.0); } + // gets total books and students from a list of schools + private MetricGeneric getGenericMetrics(List reports) { + Integer totalBooks = 0; + Integer totalStudents = 0; + + for (ReportGeneric report : reports) { + totalBooks += report.getNumberOfBooks(); + totalStudents += report.getNumberOfChildren(); + } + return new MetricGeneric(totalBooks, totalStudents); + } + private Float getCountryStudentLibrariansPerSchoolAverage( Country country, List schoolReports) { int totalCountStudentLibrarians = 0; From 1171d264011114a23d4fe6d60125f4639789382a Mon Sep 17 00:00:00 2001 From: Max Sebso Date: Sun, 2 Jan 2022 17:47:59 -0800 Subject: [PATCH 8/8] fixed generic metric --- .../ProtectedDataProcessorImpl.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java index 32620788..2a21a49e 100644 --- a/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java +++ b/service/src/main/java/com/codeforcommunity/processor/authenticated/ProtectedDataProcessorImpl.java @@ -47,7 +47,7 @@ public MetricsTotalResponse getFixedTotalMetrics(JWTData userData) { .and(SCHOOLS.DELETED_AT.isNull()) .fetch(SCHOOLS.ID); - MetricGeneric metricGeneric = getGenericMetrics(getReports(schoolIds)); + MetricGeneric metricGeneric = getGenericMetrics(schoolIds); return new MetricsTotalResponse(countSchools, metricGeneric.getTotalBooks(), metricGeneric.getTotalStudents()); @@ -78,6 +78,13 @@ public MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country c List schoolReports = this.getCountryReports(country); + List schoolIds = + db.selectFrom(SCHOOLS) + .where(SCHOOLS.HIDDEN.isFalse()) + .and(SCHOOLS.DELETED_AT.isNull()) + .and(SCHOOLS.COUNTRY.eq(country)) + .fetch(SCHOOLS.ID); + Float avgCountBooksPerStudent = this.getCountryBooksPerStudentAverage(country, schoolReports); Float avgCountStudentLibrariansPerSchool = this.getCountryStudentLibrariansPerSchoolAverage(country, schoolReports); @@ -93,7 +100,7 @@ public MetricsCountryResponse getFixedCountryMetrics(JWTData userData, Country c float percentSchoolsWithLibraries = (countSchools > 0) ? ((float) countSchoolsWithLibrary / (float) countSchools) * 100 : 0; - MetricGeneric metricGeneric = getGenericMetrics(schoolReports); + MetricGeneric metricGeneric = getGenericMetrics(schoolIds); return new MetricsCountryResponse( countSchools, @@ -197,13 +204,13 @@ private Float getCountryBooksPerStudentAverage( } // gets total books and students from a list of schools - private MetricGeneric getGenericMetrics(List reports) { + private MetricGeneric getGenericMetrics(List schoolIds) { Integer totalBooks = 0; Integer totalStudents = 0; - for (ReportGeneric report : reports) { - totalBooks += report.getNumberOfBooks(); - totalStudents += report.getNumberOfChildren(); + for (Integer schoolId : schoolIds) { + totalBooks += schoolDatabaseOperations.getMostRecentReport(schoolId).getNumberOfBooks(); + totalStudents += schoolDatabaseOperations.getMostRecentReport(schoolId).getNumberOfChildren(); } return new MetricGeneric(totalBooks, totalStudents); }