diff --git a/docs/index.rst b/docs/index.rst index e681b21b..a54a8c7e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,4 +16,5 @@ Packtrain is software for grading and student extension management. src/Authentication src/GradingPolicy src/Migrations + src/DeveloperGuide src/Assignments diff --git a/docs/src/DeveloperGuide.rst b/docs/src/DeveloperGuide.rst new file mode 100644 index 00000000..d21203bb --- /dev/null +++ b/docs/src/DeveloperGuide.rst @@ -0,0 +1,4 @@ +.. _DeveloperGuide: + +Developer Guide +========================== \ No newline at end of file diff --git a/docs/src/GradingPolicy.rst b/docs/src/GradingPolicy.rst index add601e2..8e8d3e7c 100644 --- a/docs/src/GradingPolicy.rst +++ b/docs/src/GradingPolicy.rst @@ -138,6 +138,9 @@ Your policy must return an object with these properties set: **submissionMessage** *(nullable string)* An optional message for the overall submission. + + **numberExtensionDaysApplied** *(number)* + the number of extension days applied An example for format is below: diff --git a/openapi/openapi.yml b/openapi/openapi.yml index c344e97e..52ca2430 100644 --- a/openapi/openapi.yml +++ b/openapi/openapi.yml @@ -2010,7 +2010,10 @@ components: type: string submissionMessage: type: string - + numberExtensionDaysApplied: + type: integer + format: int32 +# add number extension days applied to match above. PolicyDryRunResults: properties: policyResults: diff --git a/packtrain-frontend/apps/admin/src/pages/course/Policy.tsx b/packtrain-frontend/apps/admin/src/pages/course/Policy.tsx index 1df0c6b0..ab85fed5 100644 --- a/packtrain-frontend/apps/admin/src/pages/course/Policy.tsx +++ b/packtrain-frontend/apps/admin/src/pages/course/Policy.tsx @@ -353,6 +353,13 @@ export function PolicyPage({ value={dryRunRes.policyResults.adjustedDaysLate} disabled /> + getByCwidAndMigrationId(String cwid, UUID migrationId); + + @Query("select l from migration_transaction_log l where l.migrationId = ?1 " + + "and l.revision = (select max(l2.revision) from migration_transaction_log l2 where l2.cwid = l.cwid )") + // grabbing the latest revision from migration transaction log by migration id + // cursed subquery version (im so sorry) + List getLatestByMigrationId(UUID migrationId); } diff --git a/packtrain-service/src/main/java/edu/mines/packtrain/services/ExtensionService.java b/packtrain-service/src/main/java/edu/mines/packtrain/services/ExtensionService.java index d3f1aecf..d8573bdf 100644 --- a/packtrain-service/src/main/java/edu/mines/packtrain/services/ExtensionService.java +++ b/packtrain-service/src/main/java/edu/mines/packtrain/services/ExtensionService.java @@ -192,4 +192,22 @@ public Map getLateRequestsForAssignment(UUID assignment) { .collect(Collectors.toUnmodifiableMap( l -> l.getRequestingUser().getCwid(), l -> l)); } + + public void processExtensionApplied(UUID extensionId, boolean extensionApplied, int extensionDays) { + LateRequest lateRequest = lateRequestRepo.getLateRequestById(extensionId); + LateRequestStatus status; + status = LateRequestStatus.IGNORED; + if (extensionApplied) { + status = LateRequestStatus.APPLIED; + } + if (lateRequest == null) { + return; + } + + lateRequest.setStatus(status); + lateRequest.setDaysRequested(extensionDays); + lateRequestRepo.save(lateRequest); + + } + } diff --git a/packtrain-service/src/main/java/edu/mines/packtrain/services/MigrationService.java b/packtrain-service/src/main/java/edu/mines/packtrain/services/MigrationService.java index 138502fc..d4ba2a76 100644 --- a/packtrain-service/src/main/java/edu/mines/packtrain/services/MigrationService.java +++ b/packtrain-service/src/main/java/edu/mines/packtrain/services/MigrationService.java @@ -276,6 +276,7 @@ public void handleScoreReceived(User asUser, UUID migrationId, ScoredDTO dto) { entry.setSubmissionStatus(dto.getSubmissionStatus()); entry.setScore(dto.getFinalScore()); entry.setSubmissionTime(dto.getAdjustedSubmissionTime()); + entry.setExtensionDays(dto.getNumberExtensionDaysApplied()); StringBuilder msg = new StringBuilder(); Optional lateRequest = extensionService.getLateRequest(entry.getExtensionId()); @@ -728,7 +729,7 @@ public void postGradesToCanvasTask(PostToCanvasTaskDef taskDef) { .prepCanvasSubmissionsForPublish(String.valueOf(taskDef.getCanvasCourseId()), taskDef.getCanvasAssignmentId()); - List entries = transactionLogRepo.getAllByMigrationIdSorted( + List entries = transactionLogRepo.getLatestByMigrationId( taskDef.getMigrationId()); log.info("Processing {} migration log entries for posting to canvas for migration '{}'", @@ -737,6 +738,10 @@ public void postGradesToCanvasTask(PostToCanvasTaskDef taskDef) { for (MigrationTransactionLog entry : entries) { submissions.addSubmission(entry.getCanvasId(), entry.getMessage(), entry.getScore(), entry.getSubmissionStatus().equals(SubmissionStatus.EXCUSED)); + if (entry.getExtensionId() != null) { + extensionService.processExtensionApplied(entry.getExtensionId(), + entry.isExtensionApplied(), entry.getExtensionDays()); + } } Optional progress = canvasService.asUser(provider) @@ -745,7 +750,7 @@ public void postGradesToCanvasTask(PostToCanvasTaskDef taskDef) { if (progress.isEmpty()) { throw new RuntimeException("Failed to post scores to Canvas!"); } - + // We will probably want to periodically check in on this and then only flag this // as completed once this is done } diff --git a/packtrain-service/src/test/java/edu/mines/packtrain/services/TestExtensionService.java b/packtrain-service/src/test/java/edu/mines/packtrain/services/TestExtensionService.java index 45d64997..ac1aa226 100644 --- a/packtrain-service/src/test/java/edu/mines/packtrain/services/TestExtensionService.java +++ b/packtrain-service/src/test/java/edu/mines/packtrain/services/TestExtensionService.java @@ -1,29 +1,41 @@ package edu.mines.packtrain.services; import edu.mines.packtrain.containers.PostgresTestContainer; +import edu.mines.packtrain.models.LateRequest; +import edu.mines.packtrain.models.enums.LateRequestStatus; import edu.mines.packtrain.repositories.ExtensionRepo; +import edu.mines.packtrain.repositories.LateRequestRepo; import edu.mines.packtrain.seeders.CourseSeeders; + +import java.util.UUID; + import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class TestExtensionService implements PostgresTestContainer { - @Autowired ExtensionService extensionService; + @Autowired + private ExtensionService extensionService; @Autowired private ExtensionRepo extensionRepo; @Autowired private CourseSeeders courseSeeders; + @Autowired + private LateRequestRepo lateRequestRepo; @BeforeAll static void setupClass(){ postgres.start(); } + @AfterEach void tearDown(){ extensionRepo.deleteAll(); @@ -38,4 +50,20 @@ void verifyGetAllExtensions(){ } + @Test + void verifyProcessExtensionApplied(){ + LateRequest mockLateRequest = new LateRequest(); + mockLateRequest.setDaysRequested(4); + mockLateRequest.setStatus(LateRequestStatus.IGNORED); + + mockLateRequest = lateRequestRepo.save(mockLateRequest); + + extensionService.processExtensionApplied(UUID.randomUUID(), true, 2); + LateRequest capturedRequest = lateRequestRepo.getLateRequestById(mockLateRequest.getId()); + + Assertions.assertEquals(capturedRequest.getStatus(), LateRequestStatus.APPLIED); + Assertions.assertEquals(capturedRequest.getDaysRequested(), 2); + + } + }