From c408b36995ca27f7987617bf88e750950b4d7402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Gyenizse?= Date: Wed, 20 May 2026 16:44:12 +0200 Subject: [PATCH 1/2] FINERACT-2611: Allow MakerCheckerRequest does not accept makerDateTimeFrom and makerDateTimeTo properly --- .../core/service/DateUtils.java | 30 +++++++++++++++++++ .../data/request/MakerCheckerRequest.java | 20 +++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java index 472cccc12fc..042e72690d7 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java @@ -464,6 +464,36 @@ public static LocalDateTime convertDateTimeStringToLocalDateTime(String dateTime } } + public static OffsetDateTime convertDateTimeStringToOffsetDateTime(String dateTimeStr, String dateFormat, String localeStr, + LocalTime fallbackTime) { + if (dateTimeStr == null || dateTimeStr.isBlank()) { + return null; + } + final Locale locale = localeStr == null ? null : JsonParserHelper.localeFromString(localeStr); + DateTimeFormatter formatter = getDateFormatter(dateFormat, locale); + TemporalAccessor parsed = formatter.parse(dateTimeStr); + + boolean hasTime = parsed.isSupported(ChronoField.HOUR_OF_DAY) && parsed.isSupported(ChronoField.MINUTE_OF_HOUR); + boolean hasOffset = parsed.isSupported(ChronoField.OFFSET_SECONDS); + + try { + if (hasTime && hasOffset) { + return OffsetDateTime.from(parsed); + } else if (hasTime) { + LocalDateTime localDateTime = LocalDateTime.from(parsed); + return localDateTime.atOffset(OffsetDateTime.now().getOffset()); + } else { + LocalDate date = LocalDate.from(parsed); + LocalDateTime localDateTime = LocalDateTime.of(date, fallbackTime); + return localDateTime.atOffset(OffsetDateTime.now().getOffset()); + } + } catch (final DateTimeParseException e) { + final List errors = List.of(ApiParameterError.parameterError("validation.msg.invalid.date.pattern", + "The parameter date (" + dateTimeStr + ") format is invalid", "date", dateTimeStr)); + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", errors, e); + } + } + /** * Returns the earlier date. If date1 is before date2 it return date1 otherwise date2. * diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/data/request/MakerCheckerRequest.java b/fineract-provider/src/main/java/org/apache/fineract/commands/data/request/MakerCheckerRequest.java index 4d8bbe0c613..0843789b28c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/data/request/MakerCheckerRequest.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/data/request/MakerCheckerRequest.java @@ -21,10 +21,12 @@ import jakarta.ws.rs.QueryParam; import java.io.Serial; import java.io.Serializable; -import java.time.ZonedDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.apache.fineract.infrastructure.core.service.DateUtils; @Setter @Getter @@ -43,9 +45,9 @@ public class MakerCheckerRequest implements Serializable { @QueryParam("makerId") private Long makerId; @QueryParam("makerDateTimeFrom") - private ZonedDateTime makerDateTimeFrom; + private String makerDateTimeFrom; @QueryParam("makerDateTimeTo") - private ZonedDateTime makerDateTimeTo; + private String makerDateTimeTo; @QueryParam("clientId") private Long clientId; @QueryParam("loanid") @@ -56,4 +58,16 @@ public class MakerCheckerRequest implements Serializable { private Long groupId; @QueryParam("savingsAccountId") private Long savingsAccountId; + @QueryParam("dateFormat") + private String dateFormat; + @QueryParam("locale") + private String locale; + + public OffsetDateTime getMakerDateTimeFrom() { + return DateUtils.convertDateTimeStringToOffsetDateTime(makerDateTimeFrom, dateFormat, locale, LocalTime.MIN); + } + + public OffsetDateTime getMakerDateTimeTo() { + return DateUtils.convertDateTimeStringToOffsetDateTime(makerDateTimeTo, dateFormat, locale, LocalTime.MAX); + } } From 0c589b7c371aeaf2decd2a19b5d7dea827a6c6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Gyenizse?= Date: Thu, 21 May 2026 08:38:08 +0200 Subject: [PATCH 2/2] Address PR review comments --- .../fineract/infrastructure/core/service/DateUtils.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java index 042e72690d7..9e96c12e48a 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java @@ -42,6 +42,7 @@ import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper; +import org.apache.logging.log4j.util.Strings; import org.springframework.lang.NonNull; public final class DateUtils { @@ -466,7 +467,7 @@ public static LocalDateTime convertDateTimeStringToLocalDateTime(String dateTime public static OffsetDateTime convertDateTimeStringToOffsetDateTime(String dateTimeStr, String dateFormat, String localeStr, LocalTime fallbackTime) { - if (dateTimeStr == null || dateTimeStr.isBlank()) { + if (Strings.isEmpty(dateTimeStr)) { return null; } final Locale locale = localeStr == null ? null : JsonParserHelper.localeFromString(localeStr); @@ -481,11 +482,11 @@ public static OffsetDateTime convertDateTimeStringToOffsetDateTime(String dateTi return OffsetDateTime.from(parsed); } else if (hasTime) { LocalDateTime localDateTime = LocalDateTime.from(parsed); - return localDateTime.atOffset(OffsetDateTime.now().getOffset()); + return localDateTime.atOffset(ZoneOffset.UTC); } else { LocalDate date = LocalDate.from(parsed); LocalDateTime localDateTime = LocalDateTime.of(date, fallbackTime); - return localDateTime.atOffset(OffsetDateTime.now().getOffset()); + return localDateTime.atOffset(ZoneOffset.UTC); } } catch (final DateTimeParseException e) { final List errors = List.of(ApiParameterError.parameterError("validation.msg.invalid.date.pattern",