Skip to content
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

Closed
wants to merge 15 commits into from

Conversation

Mk9894
Copy link
Contributor

@Mk9894 Mk9894 commented May 9, 2023

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.

@jdailey jdailey added Needs Functional Review PRs which pass build and have no obvious technical problems, but need functional review. java Pull requests that update Java code labels May 9, 2023
Copy link
Contributor

@galovics galovics left a 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">&nbsp;</a>
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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;
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@galovics

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

Copy link
Contributor

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:

Anyhow, let's postpone this and keep the legacy version.

@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,
Copy link
Contributor

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);
Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

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())) {
Copy link
Contributor

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())) {
Copy link
Contributor

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];
Copy link
Contributor

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;
Copy link
Contributor

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());
Copy link
Contributor

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.

@galovics
Copy link
Contributor

Also, squash your commits pls.

Copy link
Contributor

@galovics galovics left a 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;
Copy link
Contributor

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:

Anyhow, let's postpone this and keep the legacy version.

@adamsaghy
Copy link
Contributor

@Mk9894 Please squash your commits!

@Mk9894 Mk9894 closed this Jun 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
java Pull requests that update Java code Needs Functional Review PRs which pass build and have no obvious technical problems, but need functional review.
Projects
None yet
4 participants