From 4a3ea9ce6112e8beae0eb6f4aea01537e25e3fd9 Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Mon, 23 Sep 2024 09:52:47 +0100 Subject: [PATCH 1/7] feat: Ruleset edit endpoint Added ruleset edit endpoint --- service/grails-app/controllers/org/olf/UrlMappings.groovy | 2 +- service/src/main/okapi/ModuleDescriptor-template.json | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/service/grails-app/controllers/org/olf/UrlMappings.groovy b/service/grails-app/controllers/org/olf/UrlMappings.groovy index c7d4a17..36c3e7f 100644 --- a/service/grails-app/controllers/org/olf/UrlMappings.groovy +++ b/service/grails-app/controllers/org/olf/UrlMappings.groovy @@ -16,7 +16,7 @@ class UrlMappings { "/serials-management/serials" (resources: 'serial') "/serials-management/rulesets" (resources: 'serialRuleset'){ - + '/active' (controller: 'serialRuleset', action: 'activateRuleset', method: 'POST') '/deprecated' (controller: 'serialRuleset', action: 'deprecateRuleset', method: 'POST') '/draft' (controller: 'serialRuleset', action: 'draftRuleset', method: 'POST') diff --git a/service/src/main/okapi/ModuleDescriptor-template.json b/service/src/main/okapi/ModuleDescriptor-template.json index 65b9ab4..97d2b9f 100644 --- a/service/src/main/okapi/ModuleDescriptor-template.json +++ b/service/src/main/okapi/ModuleDescriptor-template.json @@ -71,6 +71,11 @@ "pathPattern": "/serials-management/rulesets", "permissionsRequired": [ "serials-management.rulesets.item.post" ] }, + { + "methods": ["PUT"], + "pathPattern": "/serials-management/rulesets/{id}", + "permissionsRequired": [ "serials-management.rulesets.item.put" ] + }, { "methods": ["DELETE"], "pathPattern": "/serials-management/rulesets/{id}", From 2dbc96babd25f05ac9a171424e7fcd5ab09dedf9 Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Mon, 23 Sep 2024 10:52:42 +0100 Subject: [PATCH 2/7] feat: Pieceset delete endpoint Added predicted piece set delete endpoint to module descriptor, along with associated permissions --- service/src/main/okapi/ModuleDescriptor-template.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/service/src/main/okapi/ModuleDescriptor-template.json b/service/src/main/okapi/ModuleDescriptor-template.json index 97d2b9f..7b5b4b9 100644 --- a/service/src/main/okapi/ModuleDescriptor-template.json +++ b/service/src/main/okapi/ModuleDescriptor-template.json @@ -121,6 +121,11 @@ "pathPattern": "/serials-management/predictedPieces/create", "permissionsRequired": [ "serials-management.predictedPieceSets.item.post" ] }, + { + "methods": ["DELETE"], + "pathPattern": "/serials-management/predictedPieces/{id}", + "permissionsRequired": [ "serials-management.predictedPieceSets.item.delete" ] + }, { "methods": ["GET"], "pathPattern": "/serials-management/locales", From a30168cda69b02b67870d7e5ee1d620cd3f53b7f Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Thu, 26 Sep 2024 14:29:58 +0100 Subject: [PATCH 3/7] refactor: WIP Changes after call Updated Todos and changes after futher discussion --- .../olf/PredictedPieceSetController.groovy | 1 + .../org/olf/SerialRulesetController.groovy | 51 ++++++++++++++++--- .../controllers/org/olf/UrlMappings.groovy | 2 + .../org/olf/recurrence/Recurrence.groovy | 2 +- .../org/olf/HousekeepingService.groovy | 2 +- .../org/olf/SerialRulesetService.groovy | 2 +- .../main/okapi/ModuleDescriptor-template.json | 10 ++-- 7 files changed, 54 insertions(+), 16 deletions(-) diff --git a/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy b/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy index e450320..b021a28 100644 --- a/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy +++ b/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy @@ -81,6 +81,7 @@ class PredictedPieceSetController extends OkapiTenantAwareController respond result } + def replaceAndDelete() { + } + def replaceAndDeprecate() { + // TODO THis will be our ruleset 'editing' endpoint + // Only allow editing if the ruleset is in draft + // Ensure that the ruleset has no associated predicted piece sets + // Additionally ensure that if the 'replace' action fails, do NOT delete the old ruleset + SerialRuleset.withTransaction { + def data = getObjectToBind() + SerialRuleset ruleset = new SerialRuleset(data) + if(ruleset?.rulesetStatus?.value == 'active'){ + String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) + if(activeRulesetId){ + serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') + } + } + ruleset.save(failOnError: true) + if(ruleset.hasErrors()) { + transactionStatus.setRollbackOnly() + respond ruleset.errors + } + respond ruleset + } + } + + @Transactional def save() { - def data = getObjectToBind() - SerialRuleset ruleset = new SerialRuleset(data) - if(ruleset?.rulesetStatus?.value == 'active'){ - String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) - if(activeRulesetId){ - serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') + SerialRuleset.withTransaction { + def data = getObjectToBind() + SerialRuleset ruleset = new SerialRuleset(data) + if(ruleset?.rulesetStatus?.value == 'active'){ + String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) + if(activeRulesetId){ + serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') + } } + ruleset.save(failOnError: true) + if(ruleset.hasErrors()) { + transactionStatus.setRollbackOnly() + respond ruleset.errors + } + respond ruleset } - ruleset.save(flush: true, failOnError: true) - respond ruleset } } diff --git a/service/grails-app/controllers/org/olf/UrlMappings.groovy b/service/grails-app/controllers/org/olf/UrlMappings.groovy index 36c3e7f..8542197 100644 --- a/service/grails-app/controllers/org/olf/UrlMappings.groovy +++ b/service/grails-app/controllers/org/olf/UrlMappings.groovy @@ -20,6 +20,8 @@ class UrlMappings { '/active' (controller: 'serialRuleset', action: 'activateRuleset', method: 'POST') '/deprecated' (controller: 'serialRuleset', action: 'deprecateRuleset', method: 'POST') '/draft' (controller: 'serialRuleset', action: 'draftRuleset', method: 'POST') + + '/replace' (controller: 'serialRuleset', action: 'replace', method: 'POST') } "/serials-management/predictedPieces" (resources: 'predictedPieceSet') { diff --git a/service/grails-app/domain/org/olf/recurrence/Recurrence.groovy b/service/grails-app/domain/org/olf/recurrence/Recurrence.groovy index f653f54..98e562a 100644 --- a/service/grails-app/domain/org/olf/recurrence/Recurrence.groovy +++ b/service/grails-app/domain/org/olf/recurrence/Recurrence.groovy @@ -18,7 +18,7 @@ public class Recurrence implements MultiTenant { Integer issues // 7 Integer period // 3 / Frequency - + Set rules// Validate to have exactly #issues of these static belongsTo = [ diff --git a/service/grails-app/services/org/olf/HousekeepingService.groovy b/service/grails-app/services/org/olf/HousekeepingService.groovy index 8597d3a..358276a 100644 --- a/service/grails-app/services/org/olf/HousekeepingService.groovy +++ b/service/grails-app/services/org/olf/HousekeepingService.groovy @@ -82,7 +82,7 @@ class HousekeepingService { level.rawValue = level.value as Integer level.valueFormat = RefdataValue.lookupOrCreate('EnumerationNumericLevelTMRF.Format', 'Number') } - + // TODO Check this should actually be a flush level.save(flush:true, failOnError:true) } } diff --git a/service/grails-app/services/org/olf/SerialRulesetService.groovy b/service/grails-app/services/org/olf/SerialRulesetService.groovy index 9b0ee27..051b9a4 100644 --- a/service/grails-app/services/org/olf/SerialRulesetService.groovy +++ b/service/grails-app/services/org/olf/SerialRulesetService.groovy @@ -21,7 +21,7 @@ class SerialRulesetService { SerialRuleset ruleset = SerialRuleset.findById(rulesetId) ruleset.rulesetStatus = updatedStatus - ruleset.save(flush: true, failOnError: true) + ruleset.save(failOnError: true) return ruleset } diff --git a/service/src/main/okapi/ModuleDescriptor-template.json b/service/src/main/okapi/ModuleDescriptor-template.json index 7b5b4b9..40f2568 100644 --- a/service/src/main/okapi/ModuleDescriptor-template.json +++ b/service/src/main/okapi/ModuleDescriptor-template.json @@ -71,11 +71,6 @@ "pathPattern": "/serials-management/rulesets", "permissionsRequired": [ "serials-management.rulesets.item.post" ] }, - { - "methods": ["PUT"], - "pathPattern": "/serials-management/rulesets/{id}", - "permissionsRequired": [ "serials-management.rulesets.item.put" ] - }, { "methods": ["DELETE"], "pathPattern": "/serials-management/rulesets/{id}", @@ -96,6 +91,11 @@ "pathPattern": "/serials-management/rulesets/{id}/draft", "permissionsRequired": [ "serials-management.rulesets.item.put" ] }, + { + "methods": ["POST"], + "pathPattern": "/serials-management/rulesets/{id}/replace", + "permissionsRequired": [ "serials-management.rulesets.item.put" ] + }, { "methods": ["GET"], "pathPattern": "/serials-management/predictedPieces", From d8a4d3896191f411d7401e86e8687bebb670e493 Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Tue, 8 Oct 2024 12:25:32 +0100 Subject: [PATCH 4/7] feat: Added endpoints Added replaceAndDelete and replaceAndDeprecate endpoints and placeholder methods --- .../org/olf/SerialRulesetController.groovy | 21 ++++++++++++++----- .../controllers/org/olf/UrlMappings.groovy | 3 ++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/service/grails-app/controllers/org/olf/SerialRulesetController.groovy b/service/grails-app/controllers/org/olf/SerialRulesetController.groovy index 1f17699..409c719 100644 --- a/service/grails-app/controllers/org/olf/SerialRulesetController.groovy +++ b/service/grails-app/controllers/org/olf/SerialRulesetController.groovy @@ -55,14 +55,25 @@ class SerialRulesetController extends OkapiTenantAwareController } def replaceAndDelete() { - + SerialRuleset.withTransaction { + def data = getObjectToBind() + SerialRuleset ruleset = new SerialRuleset(data) + if(ruleset?.rulesetStatus?.value == 'active'){ + String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) + if(activeRulesetId){ + serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') + } + } + ruleset.save(failOnError: true) + if(ruleset.hasErrors()) { + transactionStatus.setRollbackOnly() + respond ruleset.errors + } + respond ruleset + } } def replaceAndDeprecate() { - // TODO THis will be our ruleset 'editing' endpoint - // Only allow editing if the ruleset is in draft - // Ensure that the ruleset has no associated predicted piece sets - // Additionally ensure that if the 'replace' action fails, do NOT delete the old ruleset SerialRuleset.withTransaction { def data = getObjectToBind() SerialRuleset ruleset = new SerialRuleset(data) diff --git a/service/grails-app/controllers/org/olf/UrlMappings.groovy b/service/grails-app/controllers/org/olf/UrlMappings.groovy index 8542197..7fbe7f9 100644 --- a/service/grails-app/controllers/org/olf/UrlMappings.groovy +++ b/service/grails-app/controllers/org/olf/UrlMappings.groovy @@ -21,7 +21,8 @@ class UrlMappings { '/deprecated' (controller: 'serialRuleset', action: 'deprecateRuleset', method: 'POST') '/draft' (controller: 'serialRuleset', action: 'draftRuleset', method: 'POST') - '/replace' (controller: 'serialRuleset', action: 'replace', method: 'POST') + '/replaceAndDeprecate' (controller: 'serialRuleset', action: 'replaceAndDeprecate', method: 'POST') + '/replaceAndDelete' (controller: 'serialRuleset', action: 'replaceAndDelete', method: 'POST') } "/serials-management/predictedPieces" (resources: 'predictedPieceSet') { From 448392d45879749858a4b3a040b843658152906f Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Thu, 10 Oct 2024 15:30:26 +0100 Subject: [PATCH 5/7] feat: Replace and delete/deprecate functions Added replaceAndDelete and replaceAndDeprecate functions to the serial ruleset controller class --- .../org/olf/SerialRulesetController.groovy | 39 ++++++++++++++++++- .../org/olf/SerialRulesetService.groovy | 6 +++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/service/grails-app/controllers/org/olf/SerialRulesetController.groovy b/service/grails-app/controllers/org/olf/SerialRulesetController.groovy index 409c719..a9d6d04 100644 --- a/service/grails-app/controllers/org/olf/SerialRulesetController.groovy +++ b/service/grails-app/controllers/org/olf/SerialRulesetController.groovy @@ -13,6 +13,8 @@ import grails.converters.* import grails.gorm.multitenancy.CurrentTenant import grails.gorm.transactions.Transactional +import static org.springframework.http.HttpStatus.* + import groovy.util.logging.Slf4j import java.util.regex.Pattern @@ -42,7 +44,7 @@ class SerialRulesetController extends OkapiTenantAwareController } def activateRuleset() { - String serialRulesetId = params.get("serialRulesetId") + String serialRulesetId = params.get("serialRulesetId") SerialRuleset ruleset = SerialRuleset.findById(serialRulesetId) String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) @@ -54,10 +56,29 @@ class SerialRulesetController extends OkapiTenantAwareController respond result } + @Transactional def replaceAndDelete() { SerialRuleset.withTransaction { def data = getObjectToBind() + // Existing ruleset + String existingRulesetId = params.get("serialRulesetId") + SerialRuleset existing = queryForResource(existingRulesetId) + // If existing ruleset doesnt exist, return error + if (existing == null) { + transactionStatus.setRollbackOnly() + notFound() + return + } + // Check to see if the existing ruleset has any predicted piece sets associated with it + Integer pieceSetCount = serialRulesetService.countPieceSets(existingRulesetId)[0] + if(pieceSetCount > 0){ + transactionStatus.setRollbackOnly() + render status: METHOD_NOT_ALLOWED, text: "Cannot delete a serial ruleset which has been used to generate a predicted piece set" + return + } + // New ruleset SerialRuleset ruleset = new SerialRuleset(data) + //Check to see if new ruleset is active, if it is, additionally set the current active ruleset to deprecated if(ruleset?.rulesetStatus?.value == 'active'){ String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) if(activeRulesetId){ @@ -69,14 +90,28 @@ class SerialRulesetController extends OkapiTenantAwareController transactionStatus.setRollbackOnly() respond ruleset.errors } + // Finally delete the predicted piece set if we get this far and respond. + deleteResource existing respond ruleset } } + @Transactional def replaceAndDeprecate() { SerialRuleset.withTransaction { def data = getObjectToBind() + // Existing ruleset + String existingRulesetId = params.get("serialRulesetId") + SerialRuleset existing = queryForResource(existingRulesetId) + // If existing ruleset doesnt exist, return error + if (existing == null) { + transactionStatus.setRollbackOnly() + notFound() + return + } + // New ruleset SerialRuleset ruleset = new SerialRuleset(data) + //Check to see if new ruleset is active, if it is, additionally set the current active ruleset to deprecated if(ruleset?.rulesetStatus?.value == 'active'){ String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) if(activeRulesetId){ @@ -88,6 +123,8 @@ class SerialRulesetController extends OkapiTenantAwareController transactionStatus.setRollbackOnly() respond ruleset.errors } + // Finally deprecate existing ruleset + serialRulesetService.updateRulesetStatus(existingRulesetId, 'deprecated') respond ruleset } } diff --git a/service/grails-app/services/org/olf/SerialRulesetService.groovy b/service/grails-app/services/org/olf/SerialRulesetService.groovy index 051b9a4..704d5ba 100644 --- a/service/grails-app/services/org/olf/SerialRulesetService.groovy +++ b/service/grails-app/services/org/olf/SerialRulesetService.groovy @@ -10,6 +10,12 @@ import com.k_int.web.toolkit.refdata.RefdataValue @Transactional class SerialRulesetService { + List countPieceSets(String rulesetId) { + return PredictedPieceSet.executeQuery(""" + SELECT COUNT(pps.id) from PredictedPieceSet as pps WHERE pps.ruleset.id = :rulesetId + """.toString(), [rulesetId: rulesetId,]) + } + String findActive(String serialId) { return SerialRuleset.executeQuery(""" SELECT id from SerialRuleset WHERE owner.id = :serialId AND rulesetStatus.value = :active From f4fab9311d2f573e70d3f4c5108b1e5efe0a2df0 Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Mon, 14 Oct 2024 09:53:34 +0100 Subject: [PATCH 6/7] fix: Updated endpoint permissions Added new permissions to endpoints following the standard used by the ruleset set status endpoints --- .../main/okapi/ModuleDescriptor-template.json | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/service/src/main/okapi/ModuleDescriptor-template.json b/service/src/main/okapi/ModuleDescriptor-template.json index 2714332..0bdd8f2 100644 --- a/service/src/main/okapi/ModuleDescriptor-template.json +++ b/service/src/main/okapi/ModuleDescriptor-template.json @@ -176,14 +176,14 @@ "POST" ], "pathPattern": "/serials-management/rulesets/{id}/replaceAndDeprecate", - "permissionsRequired": [ "serials-management.rulesets.item.put" ] + "permissionsRequired": [ "serials-management.rulesets.replace-deprecate.execute" ] }, { "methods": [ "POST" ], "pathPattern": "/serials-management/rulesets/{id}/replaceAndDelete", - "permissionsRequired": [ "serials-management.rulesets.item.put" ] + "permissionsRequired": [ "serials-management.rulesets.replace-delete.execute" ] }, { "methods": [ @@ -490,6 +490,16 @@ "serials-management.rulesets.item.put" ] }, + { + "permissionName": "serials-management.rulesets.replace-delete.execute", + "displayName": "Replace and delete a ruleset", + "description": "Permit the deletion and replacement of a ruleset" + }, + { + "permissionName": "serials-management.rulesets.replace-deprecate.execute", + "displayName": "Replace and deprecate a ruleset", + "description": "Permit the deprecation and replacement of a ruleset" + }, { "permissionName": "serials-management.rulesets.edit", "subPermissions": [ @@ -497,7 +507,9 @@ "serials-management.rulesets.item.post", "serials-management.rulesets.set-active.execute", "serials-management.rulesets.set-deprecated.execute", - "serials-management.rulesets.set-draft.execute" + "serials-management.rulesets.set-draft.execute", + "serials-management.rulesets.replace-delete.execute", + "serials-management.rulesets.replace-deprecate.execute" ] }, { From d2b21832cf1bd39f173fe1ae9ea32a8b0c4eaa65 Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Thu, 17 Oct 2024 23:10:02 +0100 Subject: [PATCH 7/7] refactor: Private active check method Moved logic for checking active ruleset to private method within controller --- .../org/olf/SerialRulesetController.groovy | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/service/grails-app/controllers/org/olf/SerialRulesetController.groovy b/service/grails-app/controllers/org/olf/SerialRulesetController.groovy index a9d6d04..5410b6b 100644 --- a/service/grails-app/controllers/org/olf/SerialRulesetController.groovy +++ b/service/grails-app/controllers/org/olf/SerialRulesetController.groovy @@ -56,6 +56,16 @@ class SerialRulesetController extends OkapiTenantAwareController respond result } + //Check to see if new ruleset is active, if it is, additionally set the current active ruleset to deprecated + private void activeRulesetCheck(SerialRuleset ruleset) { + if(ruleset?.rulesetStatus?.value == 'active'){ + String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) + if(activeRulesetId){ + serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') + } + } + } + @Transactional def replaceAndDelete() { SerialRuleset.withTransaction { @@ -78,13 +88,8 @@ class SerialRulesetController extends OkapiTenantAwareController } // New ruleset SerialRuleset ruleset = new SerialRuleset(data) - //Check to see if new ruleset is active, if it is, additionally set the current active ruleset to deprecated - if(ruleset?.rulesetStatus?.value == 'active'){ - String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) - if(activeRulesetId){ - serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') - } - } + activeRulesetCheck(ruleset) + ruleset.save(failOnError: true) if(ruleset.hasErrors()) { transactionStatus.setRollbackOnly() @@ -112,12 +117,8 @@ class SerialRulesetController extends OkapiTenantAwareController // New ruleset SerialRuleset ruleset = new SerialRuleset(data) //Check to see if new ruleset is active, if it is, additionally set the current active ruleset to deprecated - if(ruleset?.rulesetStatus?.value == 'active'){ - String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) - if(activeRulesetId){ - serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') - } - } + activeRulesetCheck(ruleset) + ruleset.save(failOnError: true) if(ruleset.hasErrors()) { transactionStatus.setRollbackOnly() @@ -134,12 +135,8 @@ class SerialRulesetController extends OkapiTenantAwareController SerialRuleset.withTransaction { def data = getObjectToBind() SerialRuleset ruleset = new SerialRuleset(data) - if(ruleset?.rulesetStatus?.value == 'active'){ - String activeRulesetId = serialRulesetService.findActive(ruleset?.owner?.id) - if(activeRulesetId){ - serialRulesetService.updateRulesetStatus(activeRulesetId, 'deprecated') - } - } + activeRulesetCheck(ruleset) + ruleset.save(failOnError: true) if(ruleset.hasErrors()) { transactionStatus.setRollbackOnly()