diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index 509a6f71e..0f2140efd 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -4809,4 +4809,36 @@ public class CommandWrapperBuilder { this.href = "/loans/" + loanId + "/originators/" + originatorId; return this; } + + public CommandWrapperBuilder createSurvey() { + this.actionName = "CREATE"; + this.entityName = "SURVEY"; + this.entityId = null; + this.href = "/surveys"; + return this; + } + + public CommandWrapperBuilder updateSurvey(final Long surveyId) { + this.actionName = "UPDATE"; + this.entityName = "SURVEY"; + this.entityId = surveyId; + this.href = "/surveys/" + surveyId; + return this; + } + + public CommandWrapperBuilder activateSurvey(final Long surveyId) { + this.actionName = "ACTIVATE"; + this.entityName = "SURVEY"; + this.entityId = surveyId; + this.href = "/surveys/" + surveyId; + return this; + } + + public CommandWrapperBuilder deactivateSurvey(final Long surveyId) { + this.actionName = "DEACTIVATE"; + this.entityName = "SURVEY"; + this.entityId = surveyId; + this.href = "/surveys/" + surveyId; + return this; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java index f29866125..448ed615d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java @@ -35,6 +35,7 @@ import org.apache.fineract.cob.data.OldestCOBProcessedLoanDTO; import org.apache.fineract.cob.service.LoanCOBCatchUpService; import org.apache.fineract.infrastructure.core.exception.JobIsNotFoundOrNotEnabledException; import org.apache.fineract.infrastructure.jobs.service.JobName; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.springframework.stereotype.Component; @Path("/v1/loans") @@ -44,6 +45,7 @@ import org.springframework.stereotype.Component; public class LoanCOBCatchUpApiResource { private final Optional loanCOBCatchUpServiceOp; + private final PlatformSecurityContext context; @GET @Path("oldest-cob-closed") @@ -64,6 +66,7 @@ public class LoanCOBCatchUpApiResource { @ApiResponse(responseCode = "202", description = "Catch Up has been started") @ApiResponse(responseCode = "400", description = "Catch Up is already running") public Response executeLoanCOBCatchUp() { + this.context.authenticatedUser().validateHasPermissionTo("EXECUTE_LOANCOBCATCHUP"); return loanCOBCatchUpServiceOp.map(loanCOBCatchUpService -> { if (loanCOBCatchUpService.isCatchUpRunning().isCatchUpRunning()) { return Response.status(Response.Status.BAD_REQUEST).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java index c8c6ff120..cce2ef2d2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/spm/api/SpmApiResource.java @@ -18,7 +18,6 @@ */ package org.apache.fineract.spm.api; -import com.google.gson.Gson; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -37,10 +36,14 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.spm.data.SurveyData; import org.apache.fineract.spm.domain.Survey; @@ -57,6 +60,8 @@ public class SpmApiResource { private final PlatformSecurityContext securityContext; private final SpmService spmService; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final DefaultToApiJsonSerializer toApiJsonSerializer; @GET @Consumes({ MediaType.APPLICATION_JSON }) @@ -103,12 +108,10 @@ public class SpmApiResource { @Operation(summary = "Create a Survey", description = "Adds a new survey to collect client related data.\n" + "\n" + "Mandatory Fields\n" + "\n" + "countryCode, key, name, questions, responses, sequenceNo, text, description") @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") }) - public String createSurvey(@Parameter(description = "Create survey") final SurveyData surveyData) { - this.securityContext.authenticatedUser(); - final Survey survey = SurveyMapper.map(surveyData, new Survey()); - this.spmService.createSurvey(survey); - return getResponse(survey.getId()); - + public String createSurvey(@Parameter(description = "Create survey") final String apiRequestBodyAsJson) { + final CommandWrapper commandRequest = new CommandWrapperBuilder().createSurvey().withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); } @PUT @@ -116,12 +119,10 @@ public class SpmApiResource { @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) @Transactional - public String editSurvey(@PathParam("id") final Long id, final SurveyData surveyData) { - this.securityContext.authenticatedUser(); - final Survey surveyToUpdate = this.spmService.findById(id); - final Survey survey = SurveyMapper.map(surveyData, surveyToUpdate); - this.spmService.updateSurvey(survey); - return getResponse(survey.getId()); + public String editSurvey(@PathParam("id") final Long id, final String apiRequestBodyAsJson) { + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateSurvey(id).withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); } @POST @@ -131,22 +132,17 @@ public class SpmApiResource { @Transactional @Operation(summary = "Deactivate Survey", description = "") @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") }) - public void activateOrDeactivateSurvey(@PathParam("id") final Long id, @QueryParam("command") final String command) { - this.securityContext.authenticatedUser(); + public String activateOrDeactivateSurvey(@PathParam("id") final Long id, @QueryParam("command") final String command) { + final CommandWrapperBuilder builder = new CommandWrapperBuilder(); + final CommandWrapper commandRequest; if (command != null && command.equalsIgnoreCase("activate")) { - this.spmService.activateSurvey(id); + commandRequest = builder.activateSurvey(id).build(); } else if (command != null && command.equalsIgnoreCase("deactivate")) { - this.spmService.deactivateSurvey(id); + commandRequest = builder.deactivateSurvey(id).build(); } else { throw new UnrecognizedQueryParamException("command", command); } - - } - - private String getResponse(Long id) { - Gson gson = new Gson(); - HashMap response = new HashMap<>(); - response.put("resourceId", id); - return gson.toJson(response); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/handler/ActivateSurveyCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/ActivateSurveyCommandHandler.java new file mode 100644 index 000000000..bae02b9da --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/ActivateSurveyCommandHandler.java @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.spm.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.spm.service.SpmService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SURVEY", action = "ACTIVATE") +public class ActivateSurveyCommandHandler implements NewCommandSourceHandler { + + private final SpmService spmService; + + @Autowired + public ActivateSurveyCommandHandler(final SpmService spmService) { + this.spmService = spmService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + this.spmService.activateSurvey(command.entityId()); + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withEntityId(command.entityId()) // + .build(); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/handler/CreateSurveyCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/CreateSurveyCommandHandler.java new file mode 100644 index 000000000..06c2e162f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/CreateSurveyCommandHandler.java @@ -0,0 +1,71 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.spm.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.spm.data.SurveyData; +import org.apache.fineract.spm.domain.Survey; +import org.apache.fineract.spm.service.SpmService; +import org.apache.fineract.spm.util.SurveyMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SURVEY", action = "CREATE") +public class CreateSurveyCommandHandler implements NewCommandSourceHandler { + + private final SpmService spmService; + private final ObjectMapper objectMapper; + + @Autowired + public CreateSurveyCommandHandler(final SpmService spmService, final ObjectMapper objectMapper) { + this.spmService = spmService; + this.objectMapper = objectMapper; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + final SurveyData surveyData = readSurveyData(command); + final Survey survey = SurveyMapper.map(surveyData, new Survey()); + this.spmService.createSurvey(survey); + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withEntityId(survey.getId()) // + .build(); + } + + private SurveyData readSurveyData(final JsonCommand command) { + try { + return this.objectMapper.readValue(command.json(), SurveyData.class); + } catch (final JsonProcessingException e) { + throw new PlatformDataIntegrityException("error.msg.survey.invalid.json", "Invalid survey payload: " + e.getMessage()); + } + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/handler/DeactivateSurveyCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/DeactivateSurveyCommandHandler.java new file mode 100644 index 000000000..3d9e4bfdc --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/DeactivateSurveyCommandHandler.java @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.spm.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.spm.service.SpmService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SURVEY", action = "DEACTIVATE") +public class DeactivateSurveyCommandHandler implements NewCommandSourceHandler { + + private final SpmService spmService; + + @Autowired + public DeactivateSurveyCommandHandler(final SpmService spmService) { + this.spmService = spmService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + this.spmService.deactivateSurvey(command.entityId()); + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withEntityId(command.entityId()) // + .build(); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/spm/handler/UpdateSurveyCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/UpdateSurveyCommandHandler.java new file mode 100644 index 000000000..9452e818f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/spm/handler/UpdateSurveyCommandHandler.java @@ -0,0 +1,72 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.spm.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.spm.data.SurveyData; +import org.apache.fineract.spm.domain.Survey; +import org.apache.fineract.spm.service.SpmService; +import org.apache.fineract.spm.util.SurveyMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SURVEY", action = "UPDATE") +public class UpdateSurveyCommandHandler implements NewCommandSourceHandler { + + private final SpmService spmService; + private final ObjectMapper objectMapper; + + @Autowired + public UpdateSurveyCommandHandler(final SpmService spmService, final ObjectMapper objectMapper) { + this.spmService = spmService; + this.objectMapper = objectMapper; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + final SurveyData surveyData = readSurveyData(command); + final Survey surveyToUpdate = this.spmService.findById(command.entityId()); + final Survey survey = SurveyMapper.map(surveyData, surveyToUpdate); + this.spmService.updateSurvey(survey); + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withEntityId(survey.getId()) // + .build(); + } + + private SurveyData readSurveyData(final JsonCommand command) { + try { + return this.objectMapper.readValue(command.json(), SurveyData.class); + } catch (final JsonProcessingException e) { + throw new PlatformDataIntegrityException("error.msg.survey.invalid.json", "Invalid survey payload: " + e.getMessage()); + } + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionReadPlatformServiceImpl.java index 6b5345abb..17475b1fd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/PermissionReadPlatformServiceImpl.java @@ -114,17 +114,33 @@ public class PermissionReadPlatformServiceImpl implements PermissionReadPlatform + "'SUBMITEDIT_CURRENTACCOUNT','APPROVEEDIT_CURRENTACCOUNT','REJECTEDIT_CURRENTACCOUNT'," + "'SUBMITEDIT_CLIENT','APPROVEEDIT_CLIENT','REJECTEDIT_CLIENT'"; + /* + * Unlike DEAD_MAKER_CHECKER_CODES above, these codes ARE read by the live maker-checker pipeline + * (CommandSourceService.isMakerCheckerEnabledForTask()) - they are excluded from this screen for a + * different reason: UPDATE_PERMISSION governs this very "Configure Maker Checker Tasks" screen + * (toggling which tasks require maker-checker), and UPDATE_CONFIGURATION governs the global + * maker-checker on/off switch and other System -> Configurations settings. If either were flipped + * to can_maker_checker=true and the approving checker.user lacked CHECKER_SUPER_USER, an admin + * could lock themselves out of ever approving further changes to maker-checker configuration + * itself, with no ordinary way to reverse it. Excluding them here only hides them from this + * screen; it does not touch their can_maker_checker value or their normal enforcement. + */ + private static final String SELF_REFERENTIAL_MAKER_CHECKER_CODES = "'UPDATE_PERMISSION','UPDATE_CONFIGURATION'"; + public String makerCheckerablePermissionSchema() { /* * get all 'Maker-Checkerable' permissions - Maintenance permissions (i.e. exclude the 'special' grouping, * the READ permissions and the CHECKER permissions), and exclude permission codes whose approval - * workflow does not actually read can_maker_checker (see DEAD_MAKER_CHECKER_CODES above). + * workflow does not actually read can_maker_checker (see DEAD_MAKER_CHECKER_CODES above), as well as + * codes that control maker-checker configuration itself (see SELF_REFERENTIAL_MAKER_CHECKER_CODES + * above) to avoid a self-lockout. */ return "select p.grouping, p.code, p.entity_name as entityName, p.action_name as actionName, p.can_maker_checker as selected" + " from m_permission p " + " where " + sqlGenerator.escape("grouping") + " != 'special' and code not like 'READ_%' and code not like '%\\_CHECKER'" + " and code not in (" + DEAD_MAKER_CHECKER_CODES + ")" + + " and code not in (" + SELF_REFERENTIAL_MAKER_CHECKER_CODES + ")" + " order by p.grouping, coalesce(entity_name, ''), p.code"; } diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/final-changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/final-changelog-tenant.xml index 03cb272b1..e43230fdb 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/final-changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/final-changelog-tenant.xml @@ -149,4 +149,7 @@ dev-latest's highest, 0582) to avoid ambiguity; content/semantics unchanged, only the file name and this changeset's id were updated to match. --> + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0584_add_manage_survey_permissions.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0584_add_manage_survey_permissions.xml new file mode 100644 index 000000000..68e5330ab --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0584_add_manage_survey_permissions.xml @@ -0,0 +1,68 @@ + + + + + + + SELECT COUNT(*) FROM m_permission WHERE code = 'CREATE_SURVEY' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO m_role_permission (role_id, permission_id) + SELECT r.id, p.id + FROM m_role r + JOIN m_permission p ON p.code IN ('CREATE_SURVEY', 'UPDATE_SURVEY', 'ACTIVATE_SURVEY', 'DEACTIVATE_SURVEY') + WHERE (LOWER(r.name) LIKE '%manager%' OR LOWER(r.name) = 'super user') + AND NOT EXISTS ( + SELECT 1 FROM m_role_permission rp2 + WHERE rp2.role_id = r.id AND rp2.permission_id = p.id + ) + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0585_add_loan_cob_catchup_permission.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0585_add_loan_cob_catchup_permission.xml new file mode 100644 index 000000000..9cbdd9553 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0585_add_loan_cob_catchup_permission.xml @@ -0,0 +1,44 @@ + + + + + + + SELECT COUNT(*) FROM m_permission WHERE code = 'EXECUTE_LOANCOBCATCHUP' + + + + + + + + + + + + + + INSERT INTO m_role_permission (role_id, permission_id) + SELECT r.id, p.id + FROM m_role r + JOIN m_permission p ON p.code = 'EXECUTE_LOANCOBCATCHUP' + WHERE (LOWER(r.name) LIKE '%manager%' OR LOWER(r.name) = 'super user') + AND NOT EXISTS ( + SELECT 1 FROM m_role_permission rp2 + WHERE rp2.role_id = r.id AND rp2.permission_id = p.id + ) + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0586_add_system_module_checker_permissions.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0586_add_system_module_checker_permissions.xml new file mode 100644 index 000000000..150bffec5 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0586_add_system_module_checker_permissions.xml @@ -0,0 +1,107 @@ + + + + + + + SELECT COUNT(*) FROM m_permission WHERE code = 'CREATE_ACCOUNTNUMBERFORMAT_CHECKER' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO m_role_permission (role_id, permission_id) + SELECT rp.role_id, checker.id + FROM m_role_permission rp + JOIN m_permission base ON base.id = rp.permission_id + JOIN m_permission checker ON checker.code = base.code || '_CHECKER' + WHERE base.code IN ('CREATE_ACCOUNTNUMBERFORMAT', 'UPDATE_ACCOUNTNUMBERFORMAT', 'DELETE_ACCOUNTNUMBERFORMAT', + 'CREATE_ENTITYMAPPING', 'UPDATE_ENTITYMAPPING', 'DELETE_ENTITYMAPPING', + 'CREATE_USERAGREEMENT', 'UPDATE_BATCH_BUSINESS_STEP') + AND NOT EXISTS ( + SELECT 1 FROM m_role_permission rp2 + WHERE rp2.role_id = rp.role_id AND rp2.permission_id = checker.id + ) + + + +