rymghosn commented on code in PR #6235: URL: https://github.com/apache/fineract/pull/6235#discussion_r4181350392
########## fineract-provider/src/main/resources/db/changelog/tenant/parts/0245_delete_trailing_space_standinginstruction_permissions.xml: ########## @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<!-- + Liquibase changeSet to safely delete duplicate m_permission rows + for Standing Instruction permissions WITHOUT trailing spaces, + keeping the legacy trailing-space versions. + + Deletes ONLY: + - 'CREATE_STANDINGINSTRUCTION' + - 'UPDATE_STANDINGINSTRUCTION' + - 'DELETE_STANDINGINSTRUCTION' + + Safety rules: + - Delete ONLY if a trailing-space version already exists. + - Do NOT modify or insert any permissions. + - Do NOT touch m_role_permission. + - Idempotent and safe to re-run. + - PostgreSQL only. +--> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd"> + + <changeSet id="0245_delete_non_spaced_standinginstruction_permissions" Review Comment: You were right, and my earlier reply had it backwards: the application checks the trimmed codes (`CommandWrapper` builds `CREATE_STANDINGINSTRUCTION`, and `Permission.hasCode` doesn't ignore the trailing space). The changeset now keeps the trimmed rows and deletes the trailing-space ones. Before deleting, it moves their role assignments to the trimmed rows, so the `RESTRICT` foreign key can't stop the migration and no role loses access. ########## fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionReadPlatformServiceImpl.java: ########## @@ -299,8 +299,21 @@ public Page<StandingInstructionData> retrieveAll(final StandingInstructionDTO st sqlBuilder.append(" fromsavacc.id=? "); paramObj.add(standingInstructionDTO.fromAccount()); } else if (PortfolioAccountType.LOAN.equals(accountType)) { - sqlBuilder.append(" fromloanacc.id=? "); - paramObj.add(standingInstructionDTO.fromAccount()); + // For LOAN_REPAYMENT transfers, loan is stored in to_loan_account_id (FROM=SAVINGS, TO=LOAN) Review Comment: Agreed: the result depended on the transfer type, which is fragile. A loan account filter now always matches `(toloanacc.id=? or fromloanacc.id=?)`, so the transfer type no longer decides which column is checked. ########## fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionReadPlatformServiceImpl.java: ########## @@ -299,8 +299,21 @@ public Page<StandingInstructionData> retrieveAll(final StandingInstructionDTO st sqlBuilder.append(" fromsavacc.id=? "); paramObj.add(standingInstructionDTO.fromAccount()); } else if (PortfolioAccountType.LOAN.equals(accountType)) { - sqlBuilder.append(" fromloanacc.id=? "); - paramObj.add(standingInstructionDTO.fromAccount()); + // For LOAN_REPAYMENT transfers, loan is stored in to_loan_account_id (FROM=SAVINGS, TO=LOAN) + // For other transfer types, loan is stored in from_loan_account_id + // Defensive fallback: if transferType is null, check both columns to handle UI inconsistencies + Integer transferTypeValue = standingInstructionDTO.transferType(); + if (transferTypeValue != null && transferTypeValue.equals(AccountTransferType.LOAN_REPAYMENT.getValue())) { + sqlBuilder.append(" toloanacc.id=? "); Review Comment: That branch is gone. `fromAccountId` is the account the caller filters by, so for a loan it is now matched against both loan columns. ########## fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/StandingInstructionReadPlatformServiceImpl.java: ########## @@ -299,8 +299,21 @@ public Page<StandingInstructionData> retrieveAll(final StandingInstructionDTO st sqlBuilder.append(" fromsavacc.id=? "); paramObj.add(standingInstructionDTO.fromAccount()); } else if (PortfolioAccountType.LOAN.equals(accountType)) { - sqlBuilder.append(" fromloanacc.id=? "); - paramObj.add(standingInstructionDTO.fromAccount()); + // For LOAN_REPAYMENT transfers, loan is stored in to_loan_account_id (FROM=SAVINGS, TO=LOAN) + // For other transfer types, loan is stored in from_loan_account_id + // Defensive fallback: if transferType is null, check both columns to handle UI inconsistencies + Integer transferTypeValue = standingInstructionDTO.transferType(); + if (transferTypeValue != null && transferTypeValue.equals(AccountTransferType.LOAN_REPAYMENT.getValue())) { + sqlBuilder.append(" toloanacc.id=? "); + paramObj.add(standingInstructionDTO.fromAccount()); + } else if (transferTypeValue == null) { + sqlBuilder.append(" (toloanacc.id=? OR fromloanacc.id=?) "); Review Comment: The fallback is now the only loan filter: both columns are checked whether or not `transferType` is given. That also covers `LOAN_DOWN_PAYMENT` and the other non-`LOAN_REPAYMENT` types you mentioned. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
