Skip to content

Commit

Permalink
Merge pull request #5 from openMF/enhancement/savings_accrual_transac…
Browse files Browse the repository at this point in the history
…tion

Enhancement/savings accrual transaction
  • Loading branch information
josehernandezfintecheandomx authored Sep 6, 2023
2 parents aa2e1f0 + bd376d7 commit a4b6fe8
Show file tree
Hide file tree
Showing 173 changed files with 9,247 additions and 3,151 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-docker-mariadb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}

steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-docker-postgresql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}

steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-mariadb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-mysql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-postgresql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/smoke-activemq.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}

steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/smoke-kafka.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}

steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sonarqube.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # tag=v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
with:
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ buildscript {
fineractPublishProjects = subprojects.findAll{
[
'fineract-avro-schemas',
'fineract-api',
'fineract-client',
'fineract-core',
'fineract-provider',
'fineract-investor',
'fineract-loan'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,19 +718,19 @@ public CommandWrapperBuilder undoWithdrawal(final Long clientId) {
return this;
}

public CommandWrapperBuilder createDatatable(final String datatable, final Long apptableId, final Long datatableId) {
public CommandWrapperBuilder createDatatableEntry(final String datatable, final Long apptableId, final Long datatableId) {
this.actionName = "CREATE";
commonDatatableSettings(datatable, apptableId, datatableId);
return this;
}

public CommandWrapperBuilder updateDatatable(final String datatable, final Long apptableId, final Long datatableId) {
public CommandWrapperBuilder updateDatatableEntry(final String datatable, final Long apptableId, final Long datatableId) {
this.actionName = "UPDATE";
commonDatatableSettings(datatable, apptableId, datatableId);
return this;
}

public CommandWrapperBuilder deleteDatatable(final String datatable, final Long apptableId, final Long datatableId) {
public CommandWrapperBuilder deleteDatatableEntry(final String datatable, final Long apptableId, final Long datatableId) {
this.actionName = "DELETE";
commonDatatableSettings(datatable, apptableId, datatableId);
return this;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* 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.infrastructure.core.exception;

import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.exceptionmapper.FineractExceptionMapper;
import org.springframework.context.annotation.Scope;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Component;

@Provider
@Component
@Scope("singleton")
@Slf4j
public class HttpMessageNotReadableErrorController implements ExceptionMapper<HttpMessageNotReadableException>, FineractExceptionMapper {

@Override
public Response toResponse(HttpMessageNotReadableException exception) {
final String globalisationMessageCode = "error.msg.invalid.json.data";
final String defaultUserMessage = "The referenced JSON data is invalid, validate date format as yyyy-MM-dd or other cases like String instead of Number";
log.warn("Exception: {}, Message: {}", exception.getClass().getName(), defaultUserMessage);

final ApiParameterError error = ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage);

return Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON).build();
}

@Override
public int errorCode() {
return 4001;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import jakarta.ws.rs.ext.ExceptionMapper;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

Expand All @@ -40,7 +41,8 @@ public int errorCode() {

@Override
public Response toResponse(RuntimeException runtimeException) {
return Response.status(SC_INTERNAL_SERVER_ERROR).entity(Map.of("Exception", runtimeException.getMessage()))
return Response.status(SC_INTERNAL_SERVER_ERROR)
.entity(Map.of("Exception", ObjectUtils.defaultIfNull(runtimeException.getMessage(), "No error message available")))
.type(MediaType.APPLICATION_JSON).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,12 @@ public LocalDateTime extractLocalDateTimeNamed(final String parameterName, final
parametersPassedInCommand.add(parameterName);

try {
timeFormat = timeFormat.replace("y", "u");
String strictResolveCompatibleTimeFormat = timeFormat.replace("y", "u");
final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
timeValueAsString = primitive.getAsString();
DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder().parseCaseInsensitive().parseLenient()
.appendPattern(timeFormat).toFormatter(clientApplicationLocale).withResolverStyle(ResolverStyle.STRICT);
.appendPattern(strictResolveCompatibleTimeFormat).toFormatter(clientApplicationLocale)
.withResolverStyle(ResolverStyle.STRICT);
if (StringUtils.isNotBlank(timeValueAsString)) {
value = LocalDateTime.parse(timeValueAsString, timeFormatter);
}
Expand Down Expand Up @@ -540,9 +541,9 @@ public static LocalDateTime convertDateTimeFrom(final String dateTimeAsString, f
LocalDateTime eventLocalDateTime = null;
if (StringUtils.isNotBlank(dateTimeAsString)) {
try {
dateTimeFormat = dateTimeFormat.replace("y", "u");
String strictResolveCompatibleDateTimeFormat = dateTimeFormat.replace("y", "u");
DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive().parseLenient()
.appendPattern(dateTimeFormat).optionalStart().appendPattern(" HH:mm:ss").optionalEnd()
.appendPattern(strictResolveCompatibleDateTimeFormat).optionalStart().appendPattern(" HH:mm:ss").optionalEnd()
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0).parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0).toFormatter(clientApplicationLocale)
.withResolverStyle(ResolverStyle.STRICT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
Expand Down Expand Up @@ -78,6 +79,14 @@ public static LocalDateTime getLocalDateTimeOfSystem() {
return LocalDateTime.now(ZoneId.systemDefault()).truncatedTo(ChronoUnit.SECONDS);
}

public static LocalDateTime getAuditLocalDateTime() {
return LocalDateTime.now(ZoneId.of("UTC"));
}

public static OffsetDateTime getAuditOffsetDateTime() {
return OffsetDateTime.now(ZoneOffset.UTC);
}

public static boolean isDateInTheFuture(final LocalDate localDate) {
return localDate.isAfter(getBusinessLocalDate());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,14 @@ public static Money min(Money first, Money second, Money third, boolean notNull)
return min(min(first, second, notNull), third, notNull);
}

/**
* Calculate percentage of a value
*
* @param value
* @param percentage
* @param precision
* @return
*/
public static BigDecimal percentageOf(final BigDecimal value, final BigDecimal percentage, final int precision) {
BigDecimal percentageOf = BigDecimal.ZERO;
if (isGreaterThanZero(value)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.savings.domain.search;
package org.apache.fineract.infrastructure.core.service;

import lombok.Builder;
import java.util.Locale;
import lombok.Getter;
import org.apache.fineract.portfolio.savings.DepositAccountType;
import org.apache.fineract.portfolio.savings.domain.search.SavingsTransactionSearch.Filters;
import org.springframework.data.domain.Pageable;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;

@Getter
@Builder
public class SavingsTransactionSearchParameters {
@Setter
@RequiredArgsConstructor
public class PagedLocalRequest<T> extends PagedRequest<T> {

private Long savingsId;
private String dateFormat;

private DepositAccountType depositAccountType;
private String dateTimeFormat;

private Filters filters;

private Pageable pageable;
private String locale;

public Locale getLocaleObject() {
return locale == null ? null : JsonParserHelper.localeFromString(locale);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import java.util.Optional;
import lombok.Data;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

@Data
Expand All @@ -44,7 +43,7 @@ public Optional<T> getRequest() {
return Optional.ofNullable(request);
}

public Pageable toPageable() {
public PageRequest toPageable() {
if (isEmpty(sorts)) {
return PageRequest.of(page, size);
} else {
Expand All @@ -57,16 +56,11 @@ public Pageable toPageable() {
@SuppressWarnings({ "unused" })
private static class SortOrder {

private Direction direction;
private Sort.Direction direction;
private String property;

private enum Direction {
ASC, DESC;
}

private Sort.Order toOrder() {
Sort.Direction d = Sort.Direction.fromString(direction.name());
return new Sort.Order(d, property);
return new Sort.Order(direction, property);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ public DatabaseSpecificSQLGenerator(DatabaseTypeResolver databaseTypeResolver) {
this.databaseTypeResolver = databaseTypeResolver;
}

public DatabaseType getDialect() {
return databaseTypeResolver.databaseType();
}

public String escape(String arg) {
DatabaseType dialect = databaseTypeResolver.databaseType();
if (dialect.isMySql()) {
if (databaseTypeResolver.isMySQL()) {
return format("`%s`", arg);
} else if (dialect.isPostgres()) {
} else if (databaseTypeResolver.isPostgreSQL()) {
return format("\"%s\"", arg);
}
return arg;
Expand Down Expand Up @@ -245,4 +248,19 @@ public String buildOrderBy(List<Sort.Order> orders, String alias, boolean embedd
return orderBy + orders.stream().map(e -> String.join(" ", alias(escape(e.getProperty()), alias), e.getDirection().name()))
.collect(Collectors.joining(", "));
}

public String buildInsert(@NotNull String definition, Collection<String> fields) {
if (fields == null || fields.isEmpty()) {
return "";
}
return "INSERT INTO " + escape(definition) + '(' + fields.stream().map(this::escape).collect(Collectors.joining(", "))
+ ") VALUES (?" + ", ?".repeat(fields.size() - 1) + ')';
}

public String buildUpdate(@NotNull String definition, Collection<String> fields) {
if (fields == null || fields.isEmpty()) {
return "";
}
return "UPDATE " + escape(definition) + " SET " + fields.stream().map(e -> escape(e) + " = ?").collect(Collectors.joining(", "));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ public enum JdbcJavaType {

@Override
public Object toJdbcValueImpl(@NotNull DatabaseType dialect, Object value) {
return Boolean.TRUE.equals(value) ? 1 : 0;
return value == null ? null : (Boolean.TRUE.equals(value) ? 1 : 0);
}
},
BOOLEAN(JavaType.BOOLEAN, new DialectType(JDBCType.BIT), new DialectType(JDBCType.BOOLEAN, null, "BOOL")) { //

@Override
public Object toJdbcValueImpl(@NotNull DatabaseType dialect, Object value) {
return dialect.isMySql() ? (Boolean.TRUE.equals(value) ? 1 : 0) : super.toJdbcValueImpl(dialect, value);
return (value != null && dialect.isMySql()) ? (Boolean.TRUE.equals(value) ? 1 : 0) : super.toJdbcValueImpl(dialect, value);
}
},
SMALLINT(JavaType.SHORT, new DialectType(JDBCType.SMALLINT, true), new DialectType(JDBCType.SMALLINT, null, "INT2")), //
Expand Down Expand Up @@ -78,12 +78,12 @@ public Object toJdbcValueImpl(@NotNull DatabaseType dialect, Object value) {
// seconds field, but by default, there is no explicit bound on precision
TIME(JavaType.LOCAL_TIME, new DialectType(JDBCType.TIME), new DialectType(JDBCType.TIME, null, "TIME WITHOUT TIME ZONE")), //
TIME_WITH_TIMEZONE(JavaType.OFFSET_TIME, new DialectType(JDBCType.TIME_WITH_TIMEZONE, "TIME"),
new DialectType(JDBCType.TIME_WITH_TIMEZONE, null, "TIME WITH TIME ZONE")), //
new DialectType(JDBCType.TIME_WITH_TIMEZONE, "TIME WITH TIME ZONE")), //
TIMESTAMP(JavaType.LOCAL_DATETIME, new DialectType(JDBCType.TIMESTAMP),
new DialectType(JDBCType.TIMESTAMP, null, "TIMESTAMP WITHOUT TIME ZONE")), //
DATETIME(JavaType.LOCAL_DATETIME, new DialectType(JDBCType.TIMESTAMP, "DATETIME"), new DialectType(JDBCType.TIMESTAMP)), //
TIMESTAMP_WITH_TIMEZONE(JavaType.OFFSET_DATETIME, new DialectType(JDBCType.TIMESTAMP_WITH_TIMEZONE, null, "DATETIME"),
new DialectType(JDBCType.TIMESTAMP_WITH_TIMEZONE, null, "TIMESTAMP WITH TIME ZONE", "TIMESTAMPTZ")), //
TIMESTAMP_WITH_TIMEZONE(JavaType.OFFSET_DATETIME, new DialectType(JDBCType.TIMESTAMP_WITH_TIMEZONE, "DATETIME"),
new DialectType(JDBCType.TIMESTAMP_WITH_TIMEZONE, "TIMESTAMP WITH TIME ZONE", "TIMESTAMPTZ")), //
INTERVAL(JavaType.TIME, new DialectType(JDBCType.TIME), new DialectType(JDBCType.TIME, "INTERVAL")), //
BINARY(JavaType.BINARY, new DialectType(JDBCType.BINARY, true), new DialectType(JDBCType.BINARY, "BYTEA")), //
VARBINARY(JavaType.BINARY, new DialectType(JDBCType.VARBINARY, true), new DialectType(JDBCType.VARBINARY, "BYTEA")), //
Expand Down
Loading

0 comments on commit a4b6fe8

Please sign in to comment.