New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FINERACT-1912 Savings Account Transactions query -Advanced #3158
Conversation
…ation from env variables
…to FINERACT-1912
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to the comments, there are zero tests for this new API, please add proper coverage for it.
@@ -29369,6 +29369,242 @@ <h2>Retrieve Savings Account Transaction Template:</h2> | |||
</div> | |||
</div> | |||
|
|||
<a id="savingsaccounts_transactions_list" name="savingsaccounts_transactions_list" class="old-syle-anchor"> </a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not used anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@galovics Does it mean that we can remove this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a judgement call I think. You should see if what you do breaks the web UI from Mifos.
this.context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME); | ||
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder); | ||
|
||
LocalDate fromDate = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we use an argument resolver for this instead? That way we wouldn't have to duplicate this logic anywhere but just go with a plain LocalDate in the parameter list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for sharing the information regarding the HandlerArgumentResolver. I found that HandlerArgumentResolver is specific to Spring MVC framework and I understand that the HandlerArgumentResolver interface is not directly related to the Jersey framework, which is a separate framework for building RESTful web services.
Also it seems that Fineract is indeed using the Jersey framework for handling REST requests, rather than the MVC framework.
In a Spring Boot application, we have the flexibility to choose either the Spring MVC or Jersey framework for handling REST requests. When using Spring MVC, the HandlerArgumentResolver interface allows us to customize the resolution of method arguments in controller methods. However, in the case of Jersey, an equivalent mechanism called the ParamConverterProvider interface is used to handle method arguments.
In Jersey, if we want to achieve similar functionality to the HandlerArgumentResolver, we can implement the ParamConverterProvider interface. This interface enables us to define custom conversion logic for method parameters in Jersey-based REST endpoints. The ParamConverterProvider is responsible for converting the values from incoming requests into the desired method parameter types.
Regarding your specific concern, if we choose to implement the ParamConverter interface in our custom implementation, we might not have access to the "locale" and "dateFormat" Query parameters from the Request. This could limit our ability to convert the given date string to a LocalDate object based on the specified locale and dateFormat.
Considering this, it seems more appropriate to use the legacy approach as currently implemented in the PR. This approach allows us to retrieve the "locale" and "dateFormat" Query parameters and utilize them for converting the date string to a LocalDate object, satisfying the requirements.
Thanks.
Please let me know if you have any further questions or concerns
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, it should be a jersey parameter converter.
It's possible to access other attributes like this:
- https://stackoverflow.com/questions/27584161/read-another-parameter-within-jerseys-paramconverter
- https://stackoverflow.com/questions/53657358/paramconverter-based-on-http-header-value
Anyhow, let's postpone this and keep the legacy version.
...in/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java
Show resolved
Hide resolved
@Override | ||
public Page<SavingsAccountTransactionData> retrieveAllTransactions(final Long savingsId, DepositAccountType depositAccountType, | ||
SearchParameters searchParameters, LocalDate fromDate, LocalDate toDate, | ||
@DecimalMin(value = "0", message = "must be greater than or equal to 0") BigDecimal fromAmount, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's going to evaluate this validation annotation?
@DecimalMin(value = "0", message = "must be greater than or equal to 0") BigDecimal fromAmount, | ||
@DecimalMin(value = "0", message = "must be greater than or equal to 0") BigDecimal toAmount, String transactionType) { | ||
|
||
final StringBuilder sqlBuilder = new StringBuilder(200); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a super red flag, no native queries please unless you absolutely need them. Why don't you simply use a JPQL query with a projection for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @galovics , I acknowledge your preference for using JPQL for implementation. However, it's important to note that there is a possibility of compatibility issues with the other APIs of the transaction endpoint. Specifically, the retrieveOne function of the transaction API returns a response of Type SavingsAccountTransactionData, which is a custom type. In contrast, when using JPQL, we need to return SavingsAccountTransaction as the data type, which is the entity itself. This could potentially lead to the return response being incompatible with other transaction endpoints. I would greatly appreciate hearing your thoughts on this.
Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you might wanna consider using jpa projections:
https://www.baeldung.com/spring-data-jpa-projections
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please look at the EclipseLink docs:
https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#EclipseLink_Extensions_.28EQL.29
Joins between independent entities (EL 2.4)
Another option is to do a theta join between the entities, that should be supported by JPA directly.
|
||
if (StringUtils.isNotEmpty(transactionType)) { | ||
Integer transcationTypeEnum = null; | ||
if ("deposit".equals(transactionType.toLowerCase())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magic string
Integer transcationTypeEnum = null; | ||
if ("deposit".equals(transactionType.toLowerCase())) { | ||
transcationTypeEnum = SavingsAccountTransactionType.DEPOSIT.getValue(); | ||
} else if ("withdrawal".equals(transactionType.toLowerCase())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magic string
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " "); | ||
sqlBuilder.append(this.transactionsMapper.schema()); | ||
sqlBuilder.append(" where sa.id = ? and sa.deposit_type_enum = ? "); | ||
final Object[] objectArray = new Object[12]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, this won't fly.
@@ -48,6 +49,7 @@ | |||
import org.apache.fineract.organisation.monetary.data.CurrencyData; | |||
import org.apache.fineract.organisation.staff.data.StaffData; | |||
import org.apache.fineract.organisation.staff.service.StaffReadPlatformService; | |||
import org.apache.fineract.organisation.teller.exception.InvalidDateInputException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a teller exception, why did we import it in the savings module?
if (fromDate != null || toDate != null) { | ||
if (fromDate != null && toDate != null) { | ||
if (toDate.isBefore(fromDate)) { | ||
throw new InvalidDateInputException(fromDate.toString(), toDate.toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No message, nobody will understand whats the issue without looking at the code.
Also, squash your commits pls. |
.../org/apache/fineract/portfolio/savings/api/SavingsAccountTransactionsApiResourceSwagger.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No tests, please cover the use-cases with integration/unit tests. Thanks.
Also, squash your commits.
this.context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME); | ||
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder); | ||
|
||
LocalDate fromDate = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, it should be a jersey parameter converter.
It's possible to access other attributes like this:
- https://stackoverflow.com/questions/27584161/read-another-parameter-within-jerseys-paramconverter
- https://stackoverflow.com/questions/53657358/paramconverter-based-on-http-header-value
Anyhow, let's postpone this and keep the legacy version.
@Mk9894 Please squash your commits! |
Note
Please refer #3192 for the changes. This PR will be closed
Description
Describe the changes made and why they were made.
Ignore if these details are present on the associated Apache Fineract JIRA ticket.
Checklist
Please make sure these boxes are checked before submitting your pull request - thanks!
Write the commit message as per https://github.com/apache/fineract/#pull-requests
Acknowledge that we will not review PRs that are not passing the build ("green") - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
Create/update unit or integration tests for verifying the changes made.
Follow coding conventions at https://cwiki.apache.org/confluence/display/FINERACT/Coding+Conventions.
Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
Submission is not a "code dump". (Large changes can be made "in repository" via a branch. Ask on the developer mailing list for guidance, if required.)
FYI our guidelines for code reviews are at https://cwiki.apache.org/confluence/display/FINERACT/Code+Review+Guide.