diff --git a/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/JournalEntryMapper.java b/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/JournalEntryMapper.java
index 7abb384c7..89cd5e681 100644
--- a/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/JournalEntryMapper.java
+++ b/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/JournalEntryMapper.java
@@ -18,7 +18,6 @@
*/
package org.apache.fineract.accounting.journalentry;
-import java.time.OffsetDateTime;
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
import org.apache.fineract.accounting.journalentry.data.JournalEntryData;
import org.apache.fineract.accounting.journalentry.domain.JournalEntry;
diff --git a/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java b/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java
index 059ac4845..6d48c3433 100644
--- a/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java
+++ b/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java
@@ -277,14 +277,14 @@ public class ProductToGLAccountMappingHelper {
}
final JsonArray chargeToIncomeAccountMappingArray = this.fromApiJsonHelper.extractJsonArrayNamed(arrayFragmentName, element);
- /**
+ /*
* Variable stores a map representation of charges (key) and their associated income Id's (value) extracted from
* the passed in Jsoncommand
- **/
+ */
final Map inputChargeToIncomeAccountMap = new HashMap<>();
- /***
+ /*
* Variable stores all charges which have already been mapped to Income Accounts in the system
- **/
+ */
final Set existingCharges = new HashSet<>();
if (chargeToIncomeAccountMappingArray != null) {
if (changes != null) {
@@ -301,13 +301,13 @@ public class ProductToGLAccountMappingHelper {
// If input map is empty, delete all existing mappings
if (inputChargeToIncomeAccountMap.size() == 0) {
this.accountMappingRepository.deleteAll(existingChargeToIncomeAccountMappings);
- } /**
+ } /*
* Else,
* update existing mappings OR
* delete old mappings (which are already present, but not passed in as a part of Jsoncommand)
* Create new mappings for charges that are passed in as a part of the Jsoncommand but not already present
*
- **/
+ */
else {
for (final ProductToGLAccountMapping chargeToIncomeAccountMapping : existingChargeToIncomeAccountMappings) {
final Long currentCharge = chargeToIncomeAccountMapping.getCharge().getId();
@@ -356,14 +356,14 @@ public class ProductToGLAccountMappingHelper {
.findAllPaymentTypeToFundSourceMappings(productId, portfolioProductType.getValue());
final JsonArray paymentChannelMappingArray = this.fromApiJsonHelper
.extractJsonArrayNamed(LoanProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(), element);
- /**
+ /*
* Variable stores a map representation of Payment channels (key) and their fund sources (value) extracted from
* the passed in Jsoncommand
- **/
+ */
final Map inputPaymentChannelFundSourceMap = new HashMap<>();
- /***
+ /*
* Variable stores all payment types which have already been mapped to Fund Sources in the system
- **/
+ */
final Set existingPaymentTypes = new HashSet<>();
if (paymentChannelMappingArray != null) {
if (changes != null) {
@@ -381,14 +381,14 @@ public class ProductToGLAccountMappingHelper {
// If input map is empty, delete all existing mappings
if (inputPaymentChannelFundSourceMap.isEmpty()) {
this.accountMappingRepository.deleteAll(existingPaymentChannelToFundSourceMappings);
- } /**
+ } /*
* Else,
* update existing mappings OR
* delete old mappings (which re already present, but not passed in as a part of Jsoncommand)
* Create new mappings for payment types that are passed in as a part of the Jsoncommand but not already
* present
*
- **/
+ */
else {
for (final ProductToGLAccountMapping existingPaymentChannelToFundSourceMapping : existingPaymentChannelToFundSourceMappings) {
final Long currentPaymentChannelId = existingPaymentChannelToFundSourceMapping.getPaymentType().getId();
@@ -584,9 +584,9 @@ public class ProductToGLAccountMappingHelper {
// based on input condition
GLAccount glAccount;
- /**
+ /*
* Both CASH and Accrual placeholders have the same value for income from Interest and penalties
- **/
+ */
CashAccountsForLoan placeHolderAccountType;
if (isPenalty) {
glAccount = getAccountByIdAndType(LoanProductAccountingParams.INCOME_ACCOUNT_ID.getValue(), GLAccountType.INCOME,
diff --git a/fineract-branch/src/main/java/org/apache/fineract/organisation/teller/api/TellerApiResource.java b/fineract-branch/src/main/java/org/apache/fineract/organisation/teller/api/TellerApiResource.java
index 59e79b9fc..684937c3c 100644
--- a/fineract-branch/src/main/java/org/apache/fineract/organisation/teller/api/TellerApiResource.java
+++ b/fineract-branch/src/main/java/org/apache/fineract/organisation/teller/api/TellerApiResource.java
@@ -181,12 +181,12 @@ public class TellerApiResource {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Create Cashiers", description = """
- Mandatory Fields:\s
+ Mandatory Fields:
Cashier/staff, Fromm Date, To Date, Full Day or From time and To time
- Optional Fields:\s
+ Optional Fields:
Description/Notes""")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersRequest.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersResponse.class)))
diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/CfcfrmsSimulatorLog.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/CfcfrmsSimulatorLog.java
index 2408432df..ba18f26e6 100644
--- a/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/CfcfrmsSimulatorLog.java
+++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/CfcfrmsSimulatorLog.java
@@ -23,6 +23,7 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.time.OffsetDateTime;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Simulator-side audit log for CFCFRMS (I4C/MHA) events.
@@ -69,7 +70,7 @@ public class CfcfrmsSimulatorLog extends AbstractAuditableWithUTCDateTimeCustom<
this.eventType = eventType;
this.payload = payload;
this.responsePayload = responsePayload;
- this.eventTimestamp = OffsetDateTime.now();
+ this.eventTimestamp = DateUtils.getOffsetDateTimeOfTenant();
}
public CfcfrmsSimulatorLog(final String cfcfrmsRef, final String ticketId, final String bankIfsc,
diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/ComplaintAuditLog.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/ComplaintAuditLog.java
index 6dc8ca92e..c8cc2860f 100644
--- a/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/ComplaintAuditLog.java
+++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/cfcfrms/domain/ComplaintAuditLog.java
@@ -23,6 +23,7 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.time.OffsetDateTime;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Audit trail for every status change on a CFCFRMS complaint ticket.
@@ -54,7 +55,7 @@ public class ComplaintAuditLog extends AbstractAuditableWithUTCDateTimeCustom {
form.estimatedTotalIncome = command.bigDecimalValueOfParameterNamed("estimatedTotalIncome");
form.reasonForNoPan = StringUtils.defaultIfEmpty(command.stringValueOfParameterNamed("reasonForNoPan"), null);
form.declaration = command.booleanPrimitiveValueOfParameterNamed("declaration");
- form.submittedOn = LocalDate.now();
+ form.submittedOn = DateUtils.getLocalDateOfTenant();
return form;
}
}
diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKyc.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKyc.java
index ff286a6cd..b9cb8cd05 100644
--- a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKyc.java
+++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKyc.java
@@ -32,6 +32,7 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Represents a client's KYC (Know Your Customer) record as mandated by the Reserve Bank of India
@@ -260,7 +261,7 @@ public class ClientKyc extends AbstractAuditableWithUTCDateTimeCustom {
this.gstinVerified = false;
this.cinVerified = false;
this.dinVerified = false;
- this.initiatedOn = LocalDate.now();
+ this.initiatedOn = DateUtils.getLocalDateOfTenant();
}
public static ClientKyc initiateKyc(final Client client, final JsonCommand command) {
@@ -456,13 +457,13 @@ public class ClientKyc extends AbstractAuditableWithUTCDateTimeCustom {
public void markCkycUploaded(final String ckycNumber, final String batchId) {
this.ckycNumber = StringUtils.defaultIfEmpty(ckycNumber, null);
this.ckycBatchId = StringUtils.defaultIfEmpty(batchId, null);
- this.ckycUploadedOn = LocalDate.now();
+ this.ckycUploadedOn = DateUtils.getLocalDateOfTenant();
}
/** Called after successful 3rd-party verification of all required documents. */
public void markVerified(final String ckycNumber) {
this.kycStatus = ClientKycStatus.VERIFIED.getValue();
- this.verifiedOn = LocalDate.now();
+ this.verifiedOn = DateUtils.getLocalDateOfTenant();
this.ckycNumber = StringUtils.defaultIfEmpty(ckycNumber, null);
final KycRiskCategory risk = KycRiskCategory.fromInt(this.riskCategory);
@@ -474,14 +475,14 @@ public class ClientKyc extends AbstractAuditableWithUTCDateTimeCustom {
/** Called when verification fails. */
public void markRejected(final String remarks) {
this.kycStatus = ClientKycStatus.REJECTED.getValue();
- this.rejectedOn = LocalDate.now();
+ this.rejectedOn = DateUtils.getLocalDateOfTenant();
this.remarks = StringUtils.defaultIfEmpty(remarks, this.remarks);
}
public void markPanVerified(final String fullName, final String firstName, final String lastName,
final String aadhaarSeedingStatus, final String category, final String status) {
this.panVerified = true;
- this.panVerifiedOn = LocalDate.now();
+ this.panVerifiedOn = DateUtils.getLocalDateOfTenant();
this.panFullName = StringUtils.defaultIfEmpty(fullName, null);
this.panFirstName = StringUtils.defaultIfEmpty(firstName, null);
this.panLastName = StringUtils.defaultIfEmpty(lastName, null);
@@ -507,28 +508,28 @@ public class ClientKyc extends AbstractAuditableWithUTCDateTimeCustom {
public void markAadhaarVerified() {
this.aadhaarVerified = true;
- this.aadhaarVerifiedOn = LocalDate.now();
+ this.aadhaarVerifiedOn = DateUtils.getLocalDateOfTenant();
}
public void markGstinVerified() {
this.gstinVerified = true;
- this.gstinVerifiedOn = LocalDate.now();
+ this.gstinVerifiedOn = DateUtils.getLocalDateOfTenant();
}
public void markCinVerified() {
this.cinVerified = true;
- this.cinVerifiedOn = LocalDate.now();
+ this.cinVerifiedOn = DateUtils.getLocalDateOfTenant();
}
public void markDinVerified() {
this.dinVerified = true;
- this.dinVerifiedOn = LocalDate.now();
+ this.dinVerifiedOn = DateUtils.getLocalDateOfTenant();
}
public void markDinVerified(final String dinNumber, final String mcaResponseJson) {
this.dinNumber = dinNumber;
this.dinVerified = true;
- this.dinVerifiedOn = LocalDate.now();
+ this.dinVerifiedOn = DateUtils.getLocalDateOfTenant();
this.isDirector = true;
this.dinMcaResponse = mcaResponseJson;
}
diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/mobilelookup/domain/MobileLookupLog.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/mobilelookup/domain/MobileLookupLog.java
index 51f01e935..b1a705ae2 100644
--- a/fineract-core/src/main/java/org/apache/fineract/portfolio/mobilelookup/domain/MobileLookupLog.java
+++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/mobilelookup/domain/MobileLookupLog.java
@@ -24,6 +24,7 @@ import jakarta.persistence.Table;
import java.time.OffsetDateTime;
import lombok.Getter;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Activity log for each DIP / MNRL mobile number lookup request.
@@ -78,6 +79,6 @@ public class MobileLookupLog extends AbstractAuditableWithUTCDateTimeCustom
/**
* Login gate: returns true if the user has at least one usable DSC mapping that's also not
- * past its notAfter date. The {@code dscExpiryDate >= today} clause prevents 2FA-gating a
+ * past its notAfter date. The {@code dscExpiryDate >= today} clause prevents 2FA-gating a
* user who's enrolled but whose cert silently expired between log-ins — they'd otherwise be
* stuck in a verification loop with a cert the helper would sign with but the server would
* accept (the verify side filters too, but the gate is what kicks the user into the DSC flow
diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccountPendingEdit.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccountPendingEdit.java
index 3b418d7d2..9631ee749 100644
--- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccountPendingEdit.java
+++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccountPendingEdit.java
@@ -29,6 +29,7 @@ import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.useradministration.domain.AppUser;
/**
@@ -452,7 +453,7 @@ public class CurrentAccountPendingEdit extends AbstractPersistableCustom {
public CurrentAccountPendingEdit(final CurrentAccount currentAccount, final AppUser maker) {
this.currentAccount = currentAccount;
this.maker = maker;
- this.createdOn = LocalDateTime.now();
+ this.createdOn = DateUtils.getLocalDateTimeOfTenant();
this.status = STATUS_PENDING;
this.pendingLockKey = lockKeyFor(currentAccount.getId());
}
@@ -582,14 +583,14 @@ public class CurrentAccountPendingEdit extends AbstractPersistableCustom {
public void markApproved(final AppUser checker) {
this.status = STATUS_APPROVED;
this.checker = checker;
- this.checkedOn = LocalDateTime.now();
+ this.checkedOn = DateUtils.getLocalDateTimeOfTenant();
this.pendingLockKey = null;
}
public void markRejected(final AppUser checker, final String reason) {
this.status = STATUS_REJECTED;
this.checker = checker;
- this.checkedOn = LocalDateTime.now();
+ this.checkedOn = DateUtils.getLocalDateTimeOfTenant();
this.rejectReason = reason;
this.pendingLockKey = null;
}
diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountNumberGenerator.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountNumberGenerator.java
index ca585310b..df8be57cd 100644
--- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountNumberGenerator.java
+++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountNumberGenerator.java
@@ -51,7 +51,9 @@ public class CurrentAccountNumberGenerator {
if (val > maxVal) {
maxVal = val;
}
- } catch (NumberFormatException ignored) {}
+ } catch (NumberFormatException ignored) {
+ // non-numeric suffix - skip when computing the max existing sequence
+ }
}
}
diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/data/CurrentProductDataValidator.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/data/CurrentProductDataValidator.java
index d91ff0219..8d09d6b64 100644
--- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/data/CurrentProductDataValidator.java
+++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/data/CurrentProductDataValidator.java
@@ -54,7 +54,6 @@ import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.math.BigDecimal;
-import java.time.MonthDay;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -76,7 +75,6 @@ import org.apache.fineract.portfolio.savings.DepositAccountType;
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
-import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProduct;
import org.apache.fineract.portfolio.savings.data.SavingsProductAccountingDataValidator;
diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProduct.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProduct.java
index 69d33752b..947885750 100644
--- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProduct.java
+++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProduct.java
@@ -56,18 +56,11 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountT
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.customerSegmentParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.productCodeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.glAccountIdParamName;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveDateParamName;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveToParamName;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.endDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerRequiredParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shareLinkingEnabledParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominationFacilityParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dormancyAlertParamName;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculateSelectorParamName;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.averagePeriodParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoPostParamName;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.frequencyFixDayParamName;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lastInterestDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enableLockinPeriodParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.balanceSwapOptionParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.msmeParamName;
diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProductDepositLimitKyc.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProductDepositLimitKyc.java
index ae7dc9ab8..279fa49e2 100644
--- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProductDepositLimitKyc.java
+++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/domain/CurrentProductDepositLimitKyc.java
@@ -26,6 +26,7 @@ import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Entity
@Table(name = "m_current_product_deposit_limit_kyc")
@@ -57,12 +58,12 @@ public class CurrentProductDepositLimitKyc extends AbstractPersistableCustom
private LocalDateTime createdDate;
protected CurrentProductFacilityLimit() {
- this.createdDate = LocalDateTime.now();
}
private CurrentProductFacilityLimit(CurrentProduct currentProduct, String limitType,
@@ -62,6 +62,7 @@ public class CurrentProductFacilityLimit extends AbstractPersistableCustom
this.generalLimit = generalLimit;
this.minorAccountLimit = minorAccountLimit;
this.smallSavingLimit = smallSavingLimit;
+ this.createdDate = DateUtils.getLocalDateTimeOfTenant();
}
public static CurrentProductFacilityLimit create(CurrentProduct currentProduct, String limitType,
diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/service/CurrentProductReadPlatformServiceImpl.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/service/CurrentProductReadPlatformServiceImpl.java
index 08aca6829..e3625015b 100644
--- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/service/CurrentProductReadPlatformServiceImpl.java
+++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentproduct/service/CurrentProductReadPlatformServiceImpl.java
@@ -19,13 +19,11 @@
package org.apache.fineract.portfolio.currentproduct.service;
import com.google.gson.Gson;
-import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java
index d49026418..9521a44d3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java
@@ -75,7 +75,7 @@ import org.springframework.stereotype.Component;
@Path("/v1/journalentries")
@Component
@Tag(name = "Journal Entries", description = """
- A journal entry refers to the logging of transactions against general ledger accounts. A journal entry may consist of several line items, each of which is either a "debit" or a "credit". The total amount of the debits must equal the total amount of the credits or the journal entry is said to be "unbalanced"\s
+ A journal entry refers to the logging of transactions against general ledger accounts. A journal entry may consist of several line items, each of which is either a "debit" or a "credit". The total amount of the debits must equal the total amount of the credits or the journal entry is said to be "unbalanced"
A journal entry directly changes the account balances on the general ledger""")
@RequiredArgsConstructor
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/email/service/EmailTemplateServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/email/service/EmailTemplateServiceImpl.java
index cacf4b0ed..c7fa18e22 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/email/service/EmailTemplateServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/email/service/EmailTemplateServiceImpl.java
@@ -21,6 +21,7 @@ package org.apache.fineract.infrastructure.email.service;
import java.time.Year;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Service
public class EmailTemplateServiceImpl implements EmailTemplateService {
@@ -129,7 +130,7 @@ public class EmailTemplateServiceImpl implements EmailTemplateService {
+ escape(supportEmail) + ""
+ "
"
+ " "
- + " © " + Year.now().getValue() + " " + escape(brandName) + ". All rights reserved."
+ + " © " + Year.now(DateUtils.getDateTimeZoneOfTenant()).getValue() + " " + escape(brandName) + ". All rights reserved."
+ "
"
+ " "
+ " "
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/crypto/ImpsCryptoUtil.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/crypto/ImpsCryptoUtil.java
index 2b79999f1..44ce44a64 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/crypto/ImpsCryptoUtil.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/crypto/ImpsCryptoUtil.java
@@ -109,6 +109,7 @@ public class ImpsCryptoUtil {
}
/** Decrypt inbound payload using the CBS private key. */
+ @SuppressWarnings("StringSplitter")
public String decryptJson(String encryptedPayload) {
if (cbsPrivateKey == null) {
throw new IllegalStateException("CBS private key not loaded — check fineract.imps.cbs.private-key-path");
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/service/ImpsCbsServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/service/ImpsCbsServiceImpl.java
index 6520a8ffe..cfe3660c8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/service/ImpsCbsServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/imps/service/ImpsCbsServiceImpl.java
@@ -34,6 +34,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* STUB implementation — returns hard-coded SUCCESS for every request and
@@ -108,7 +109,7 @@ public class ImpsCbsServiceImpl implements ImpsCbsService {
resp.setRefId(request.getRefId());
resp.setUtr(request.getUtr());
resp.setAmount(request.getAmount());
- resp.setTimeStamp(OffsetDateTime.now().format(ISO_OFFSET));
+ resp.setTimeStamp(OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()).format(ISO_OFFSET));
resp.setStatus("SUCCESS");
resp.setResponseCode("00");
AccountData payeeAcc = Optional.ofNullable(request.getPayee()).map(PartyData::getAccount).orElse(null);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openproject/service/OpenProjectService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openproject/service/OpenProjectService.java
index 3ef36d4ac..2f5cbc9e7 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openproject/service/OpenProjectService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/openproject/service/OpenProjectService.java
@@ -28,7 +28,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Credentials;
import okhttp3.MediaType;
@@ -42,6 +41,7 @@ import org.apache.fineract.infrastructure.openproject.data.OpenProjectProjectDat
import org.apache.fineract.infrastructure.openproject.data.OpenProjectStatusSummaryData;
import org.apache.fineract.infrastructure.openproject.data.OpenProjectWorkPackageData;
import org.springframework.stereotype.Service;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Service
@Slf4j
@@ -164,7 +164,7 @@ public class OpenProjectService {
}
// Set required custom field: "Last Follow-up Date" (customField8)
- body.addProperty("customField8", LocalDate.now().toString());
+ body.addProperty("customField8", LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString());
if (typeName != null && !typeName.isBlank()) {
JsonObject links = new JsonObject();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/rbifeed/service/RbiFeedFetchService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/rbifeed/service/RbiFeedFetchService.java
index 1d97d05d0..4dc27a0d6 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/rbifeed/service/RbiFeedFetchService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/rbifeed/service/RbiFeedFetchService.java
@@ -47,6 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Service
@RequiredArgsConstructor
@@ -127,7 +128,7 @@ public class RbiFeedFetchService {
NodeList items = doc.getElementsByTagName("item");
log.debug("RBI FeedFetchService - Parsed {} items from RSS for category: {}", items.getLength(), category);
List newItems = new ArrayList<>();
- LocalDateTime now = LocalDateTime.now();
+ LocalDateTime now = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant());
for (int i = 0; i < items.getLength(); i++) {
Element item = (Element) items.item(i);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/EmailLoginOtpApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/EmailLoginOtpApiResource.java
index a98b1f057..7bd8c7761 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/EmailLoginOtpApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/EmailLoginOtpApiResource.java
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.infrastructure.security.otp.api;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.swagger.v3.oas.annotations.Operation;
@@ -107,7 +109,7 @@ public class EmailLoginOtpApiResource {
}
final String fwd = req.getHeader("X-Forwarded-For");
if (fwd != null && !fwd.isBlank()) {
- return fwd.split(",")[0].trim();
+ return Iterables.get(Splitter.on(',').split(fwd), 0).trim();
}
return req.getRemoteAddr();
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/LoginOtpApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/LoginOtpApiResource.java
index a7f1e78d6..c1c739abf 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/LoginOtpApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/api/LoginOtpApiResource.java
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.infrastructure.security.otp.api;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.swagger.v3.oas.annotations.Operation;
@@ -107,7 +109,7 @@ public class LoginOtpApiResource {
}
final String fwd = req.getHeader("X-Forwarded-For");
if (fwd != null && !fwd.isBlank()) {
- return fwd.split(",")[0].trim();
+ return Iterables.get(Splitter.on(',').split(fwd), 0).trim();
}
return req.getRemoteAddr();
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/service/EmailLoginOtpServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/service/EmailLoginOtpServiceImpl.java
index 80969e691..b732ad8a4 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/service/EmailLoginOtpServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/otp/service/EmailLoginOtpServiceImpl.java
@@ -45,6 +45,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Service
public class EmailLoginOtpServiceImpl implements EmailLoginOtpService {
@@ -128,7 +129,7 @@ public class EmailLoginOtpServiceImpl implements EmailLoginOtpService {
// Render the branded template — same look and feel for OTP, welcome, password-reset, alerts.
final String html = emailTemplateService.renderOtp(recipientName, otp, validityMinutes);
- final String subject = "Your OTP for Login - " + appName + " (" + LocalDateTime.now().format(SUBJECT_TIMESTAMP) + ")";
+ final String subject = "Your OTP for Login - " + appName + " (" + LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()).format(SUBJECT_TIMESTAMP) + ")";
final boolean sent = emailSenderService.sendHtml(email, subject, html);
if (sent) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java
index a2475b4c2..f4aaf9f4a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerWritePlatformServiceJpaImpl.java
@@ -20,7 +20,6 @@ package org.apache.fineract.organisation.teller.service;
import jakarta.persistence.PersistenceException;
import java.util.Map;
-import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -44,7 +43,6 @@ import org.apache.fineract.organisation.teller.domain.CashierTransactionReposito
import org.apache.fineract.organisation.teller.domain.CashierTxnType;
import org.apache.fineract.organisation.teller.domain.Teller;
import org.apache.fineract.organisation.teller.domain.TellerRepositoryWrapper;
-import org.apache.fineract.organisation.teller.exception.CashierExistForTellerException;
import org.apache.fineract.organisation.teller.exception.CashierNotFoundException;
import org.apache.fineract.organisation.teller.exception.TellerAlreadyExistsException;
import org.apache.fineract.organisation.teller.serialization.TellerCommandFromApiJsonDeserializer;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashexchange/api/CashExchangeApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashexchange/api/CashExchangeApiResource.java
index 367433ddf..3ec138689 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashexchange/api/CashExchangeApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashexchange/api/CashExchangeApiResource.java
@@ -33,6 +33,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Path("/v1/cashexchange")
@Component
@@ -94,7 +95,7 @@ public class CashExchangeApiResource {
header.setNote(note);
header.setCustomerIdProof(customerIdProof);
header.setIsReversed(false);
- header.setCreatedAt(LocalDateTime.now());
+ header.setCreatedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
try {
AppUser user = this.context.authenticatedUser();
if (user != null) {
@@ -107,7 +108,9 @@ public class CashExchangeApiResource {
+ "JOIN m_appuser au ON au.staff_id = ms.id WHERE au.id = ?",
Long.class, user.getId());
header.setCashierId(cashierId);
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
}
} catch (Exception e) {
// resolving the current user must never block recording the exchange
@@ -160,14 +163,18 @@ public class CashExchangeApiResource {
try {
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
reason = json.has("reason") && !json.get("reason").isJsonNull() ? json.get("reason").getAsString() : null;
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
exchange.setIsReversed(true);
- exchange.setReversedAt(LocalDateTime.now());
+ exchange.setReversedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
exchange.setReverseReason(reason);
try {
AppUser user = this.context.authenticatedUser();
if (user != null) exchange.setReversedBy(user.getId());
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
repository.save(exchange);
JsonObject result = new JsonObject();
result.addProperty("resourceId", id);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashierdeposit/api/CashierDepositRequestApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashierdeposit/api/CashierDepositRequestApiResource.java
index 28b7389fd..2474b9c70 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashierdeposit/api/CashierDepositRequestApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashierdeposit/api/CashierDepositRequestApiResource.java
@@ -59,6 +59,9 @@ import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import com.google.common.collect.Iterables;
+import com.google.common.base.Splitter;
@Path("/v1/cashier/deposit-requests")
@Component
@@ -364,7 +367,7 @@ public class CashierDepositRequestApiResource {
final BigDecimal amount = new BigDecimal(record.get("amount").toString());
final Object ptId = record.get("payment_type_id");
final Object txnDateObj = record.get("txn_date");
- final String txnDateStr = txnDateObj != null ? txnDateObj.toString().split(" ")[0] : null;
+ final String txnDateStr = txnDateObj != null ? Iterables.get(Splitter.on(' ').split(txnDateObj.toString()), 0) : null;
final String description = (String) record.get("description");
final String storedAccountType = (String) record.get("account_type");
@@ -513,7 +516,7 @@ public class CashierDepositRequestApiResource {
final BigDecimal amount = new BigDecimal(record.get("amount").toString());
final Object ptId = record.get("payment_type_id");
final Object txnDateObj = record.get("txn_date");
- final String txnDateStr = txnDateObj != null ? txnDateObj.toString().split(" ")[0] : null;
+ final String txnDateStr = txnDateObj != null ? Iterables.get(Splitter.on(' ').split(txnDateObj.toString()), 0) : null;
final String description = (String) record.get("description");
if (savingsAccountId == null || !isCurrentAccountById(savingsAccountId)) {
@@ -559,7 +562,7 @@ public class CashierDepositRequestApiResource {
final Long savingsAccountId, final BigDecimal amount,
final Object paymentTypeId, final String txnDateStr, final String note) {
- final String today = LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ final String today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
final String date = txnDateStr != null && !txnDateStr.isBlank() ? formatForFineract(txnDateStr) : today;
final JsonObject payload = new JsonObject();
@@ -587,7 +590,7 @@ public class CashierDepositRequestApiResource {
final Long currentAccountId, final BigDecimal amount,
final Object paymentTypeId, final String txnDateStr, final String note) {
- final String today = LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ final String today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
final String date = txnDateStr != null && !txnDateStr.isBlank() ? formatForFineract(txnDateStr) : today;
final JsonObject payload = new JsonObject();
@@ -644,7 +647,7 @@ public class CashierDepositRequestApiResource {
final Object paymentTypeId, final String txnDateStr, final String note,
final boolean isDeposit) {
- final String today = LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ final String today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
final String date = txnDateStr != null && !txnDateStr.isBlank() ? formatForFineract(txnDateStr) : today;
// Deposit (CR): cashier receives cash → credit selected GL, debit cash vault (contra)
@@ -686,67 +689,6 @@ public class CashierDepositRequestApiResource {
return result.getTransactionId() != null ? result.getTransactionId() : null;
}
- private void saveGlDenomination(final String denominationData,
- final Map, ?> record, final String txnIdRaw) {
- final JsonObject denomMap;
- try {
- denomMap = gson.fromJson(denominationData, JsonObject.class);
- } catch (Exception e) {
- return;
- }
- if (denomMap == null || denomMap.size() == 0) return;
-
- // Convert hex transaction ID to Long (same logic as CashierGlDenominationApiResource)
- Long txnId = null;
- if (txnIdRaw != null && !txnIdRaw.isBlank()) {
- try {
- txnId = Long.valueOf(txnIdRaw);
- } catch (NumberFormatException ignored) {
- try {
- final String hex = txnIdRaw.length() > 15 ? txnIdRaw.substring(txnIdRaw.length() - 15) : txnIdRaw;
- txnId = Long.parseUnsignedLong(hex, 16);
- } catch (NumberFormatException ignored2) {
- txnId = null;
- }
- }
- }
-
- final String accountNo = (String) record.get("account_no");
- final Object cashierIdObj = record.get("cashier_id");
- final Long cashierId = cashierIdObj != null ? Long.valueOf(cashierIdObj.toString()) : null;
- final String cashierUsername = (String) record.get("cashier_username");
-
- for (final Map.Entry entry : denomMap.entrySet()) {
- final int count;
- try { count = entry.getValue().getAsInt(); } catch (Exception e) { continue; }
- if (count <= 0) continue;
-
- final String[] parts = entry.getKey().split(":", 2);
- if (parts.length != 2) continue;
- final String kind = parts[0];
- final int value;
- try { value = Integer.parseInt(parts[1]); } catch (Exception e) { continue; }
-
- final List ids = jdbcTemplate.queryForList(
- "SELECT id FROM m_denomination_master WHERE denomination = ? AND kind = ?"
- + " AND (deleted IS NULL OR deleted = false) LIMIT 1",
- Long.class, value, kind);
- if (ids.isEmpty()) continue;
- final Long denomId = ids.get(0);
-
- jdbcTemplate.update("""
- INSERT INTO m_savings_txn_denomination
- (txn_id, savings_account_id, account_no, client_id, denomination_id,
- denomination_value, count, total_amount, txn_date, txn_type, officer_id, officer_username)
- VALUES (?, NULL, ?, NULL, ?, ?, ?, ?, CURRENT_DATE, 'DEPOSIT', ?, ?)
- """,
- txnId, accountNo, denomId,
- value, count, BigDecimal.valueOf((long) value * count),
- cashierId, cashierUsername
- );
- }
- }
-
/**
* Saves the denomination breakdown the cashier entered at submit time into
* m_savings_txn_denomination once the deposit is approved, so the cashier's
@@ -797,56 +739,6 @@ public class CashierDepositRequestApiResource {
}
}
- private void saveDepositDenomination(final String denominationData,
- final Map, ?> record, final Long txnId) {
- final JsonObject denomMap;
- try {
- denomMap = gson.fromJson(denominationData, JsonObject.class);
- } catch (Exception e) {
- return; // malformed JSON — skip silently
- }
- if (denomMap == null || denomMap.size() == 0) return;
-
- final Object saObj = record.get("savings_account_id");
- final Long savingsAccountId = saObj != null ? Long.valueOf(saObj.toString()) : null;
- final String accountNo = (String) record.get("account_no");
- final Object clientIdObj = record.get("client_id");
- final Long clientId = clientIdObj != null ? Long.valueOf(clientIdObj.toString()) : null;
- final Object cashierIdObj = record.get("cashier_id");
- final Long cashierId = cashierIdObj != null ? Long.valueOf(cashierIdObj.toString()) : null;
- final String cashierUsername = (String) record.get("cashier_username");
-
- for (final Map.Entry entry : denomMap.entrySet()) {
- final int count;
- try { count = entry.getValue().getAsInt(); } catch (Exception e) { continue; }
- if (count <= 0) continue;
-
- final String[] parts = entry.getKey().split(":", 2); // "note:500" or "coin:1"
- if (parts.length != 2) continue;
- final String kind = parts[0];
- final int value;
- try { value = Integer.parseInt(parts[1]); } catch (Exception e) { continue; }
-
- final List ids = jdbcTemplate.queryForList(
- "SELECT id FROM m_denomination_master WHERE denomination = ? AND kind = ?"
- + " AND (deleted IS NULL OR deleted = false) LIMIT 1",
- Long.class, value, kind);
- if (ids.isEmpty()) continue;
- final Long denomId = ids.get(0);
-
- jdbcTemplate.update("""
- INSERT INTO m_savings_txn_denomination
- (txn_id, savings_account_id, account_no, client_id, denomination_id,
- denomination_value, count, total_amount, txn_date, txn_type, officer_id, officer_username)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'DEPOSIT', ?, ?)
- """,
- txnId, savingsAccountId, accountNo, clientId, denomId,
- value, count, BigDecimal.valueOf((long) value * count),
- cashierId, cashierUsername
- );
- }
- }
-
/**
* If a cash denomination breakdown is provided, its total must exactly equal
* the deposit amount — prevents the recorded vault movement from drifting
@@ -946,7 +838,7 @@ public class CashierDepositRequestApiResource {
final LocalDate ld = LocalDate.parse(isoDate, DateTimeFormatter.ISO_LOCAL_DATE);
return ld.format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
} catch (Exception e) {
- return LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ return LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashintercashier/api/CashInterCashierApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashintercashier/api/CashInterCashierApiResource.java
index a3d76e4f5..2f72e2ad2 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashintercashier/api/CashInterCashierApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashintercashier/api/CashInterCashierApiResource.java
@@ -31,6 +31,7 @@ import org.apache.fineract.portfolio.cashintercashier.domain.CashInterCashierRep
import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Path("/v1/cashintercashier")
@Component
@@ -69,7 +70,7 @@ public class CashInterCashierApiResource {
}
final LocalDate transferDate = json.has("transferDate") && !json.get("transferDate").isJsonNull()
- ? LocalDate.parse(json.get("transferDate").getAsString()) : LocalDate.now();
+ ? LocalDate.parse(json.get("transferDate").getAsString()) : LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
final String fromParty = json.has("fromParty") && !json.get("fromParty").isJsonNull()
? json.get("fromParty").getAsString() : null;
final String toParty = json.has("toParty") && !json.get("toParty").isJsonNull()
@@ -95,13 +96,15 @@ public class CashInterCashierApiResource {
header.setToParty(toParty);
header.setTransferAmount(total);
header.setNote(note);
- header.setCreatedAt(LocalDateTime.now());
+ header.setCreatedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
header.setIsReversed(false);
try {
AppUser user = this.context.authenticatedUser();
header.setPerformedBy(user.getId());
header.setPerformedByUsername(user.getUsername());
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
CashInterCashier saved = repository.saveAndFlush(header);
saveDetails(saved.getId(), denominations);
@@ -128,13 +131,17 @@ public class CashInterCashierApiResource {
try {
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
reason = json.has("reason") ? json.get("reason").getAsString() : null;
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
AppUser user = null;
- try { user = this.context.authenticatedUser(); } catch (Exception ignored) {}
+ try { user = this.context.authenticatedUser(); } catch (Exception ignored) {
+ // intentionally ignored
+ }
record.setIsReversed(true);
- record.setReversedAt(LocalDateTime.now());
+ record.setReversedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
record.setReverseReason(reason);
if (user != null) record.setReversedBy(user.getId());
repository.save(record);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreconciliation/api/CashReconciliationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreconciliation/api/CashReconciliationApiResource.java
index 9d8cf0325..cc922d638 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreconciliation/api/CashReconciliationApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreconciliation/api/CashReconciliationApiResource.java
@@ -32,6 +32,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Path("/v1/cashreconciliation")
@Component
@@ -62,7 +63,7 @@ public class CashReconciliationApiResource {
throw new PlatformDataIntegrityException("error.msg.cashreconciliation.cashier.required",
"cashierId query param is required.");
}
- final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now().toString();
+ final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
// In: vault → cashier allocations — GROUP BY denomination_id+kind to keep coin and note separate
final String sqlIn1 = "SELECT ctd.denomination_id, ctd.denomination_value, COALESCE(dm.kind, 'note') AS kind, SUM(ctd.count) AS total_count "
@@ -187,7 +188,7 @@ public class CashReconciliationApiResource {
@Path("expected/me")
public String getExpectedForMe(@QueryParam("asOfDate") String asOfDate) {
context.authenticatedUser().validateHasPermissionTo("READ_CASHRECONCILIATION");
- final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now().toString();
+ final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
Long appUserId;
try {
appUserId = context.authenticatedUser().getId();
@@ -223,7 +224,7 @@ public class CashReconciliationApiResource {
throw new PlatformDataIntegrityException("error.msg.cashreconciliation.cashier.required",
"cashierId query param is required.");
}
- final String reconDate = (date != null && !date.isBlank()) ? date : LocalDate.now().toString();
+ final String reconDate = (date != null && !date.isBlank()) ? date : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
Integer count = jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM m_cash_reconciliation WHERE cashier_id = ? AND recon_date = CAST(? AS DATE)",
Integer.class, cashierId, reconDate);
@@ -247,7 +248,7 @@ public class CashReconciliationApiResource {
"cashierId is required.");
}
final LocalDate reconDate = json.has("reconDate") && !json.get("reconDate").isJsonNull()
- ? LocalDate.parse(json.get("reconDate").getAsString()) : LocalDate.now();
+ ? LocalDate.parse(json.get("reconDate").getAsString()) : LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
final String cashierName = json.has("cashierName") && !json.get("cashierName").isJsonNull()
? json.get("cashierName").getAsString() : null;
final Long tellerId = json.has("tellerId") && !json.get("tellerId").isJsonNull()
@@ -299,12 +300,14 @@ public class CashReconciliationApiResource {
header.setVariance(variance);
header.setStatus(status);
header.setNote(note);
- header.setCreatedAt(LocalDateTime.now());
+ header.setCreatedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
try {
AppUser user = this.context.authenticatedUser();
header.setPerformedBy(user.getId());
header.setPerformedByUsername(user.getUsername());
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
CashReconciliation saved = repository.saveAndFlush(header);
for (CashReconciliationDetail d : details) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java
index 3e29e1d0c..f0cb31fce 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java
@@ -18,6 +18,7 @@ import org.apache.fineract.portfolio.cashreport.service.CashierRoleHelper;
import org.apache.fineract.portfolio.denominationmaster.service.DenominationBreakdownWriter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Path("/v1/cashreports")
@Component
@@ -34,7 +35,7 @@ public class CashReportApiResource {
@GET
@Path("closing")
public String closing(@QueryParam("date") String date) {
- final String txnDate = (date != null && !date.isBlank()) ? date : LocalDate.now().toString();
+ final String txnDate = (date != null && !date.isBlank()) ? date : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
// Single query — conditional aggregation for deposit, withdrawal, net per denomination
final String sql = "SELECT std.denomination_id, std.denomination_value, COALESCE(dm.kind, 'note') AS kind, "
@@ -238,7 +239,7 @@ public class CashReportApiResource {
return gson.toJson(result);
}
- final String today = LocalDate.now().toString();
+ final String today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
// Find the earliest transfer date before today for which no settlement exists on or after that date
final String sql = "SELECT MIN(ct.transfer_date) AS earliest_unsettled "
@@ -256,7 +257,9 @@ public class CashReportApiResource {
java.sql.Date earliestDate = null;
try {
earliestDate = jdbcTemplate.queryForObject(sql, java.sql.Date.class, cashierId, today, cashierId);
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
final boolean unsettled = earliestDate != null;
final String unsettledSince = earliestDate != null ? earliestDate.toString() : null;
@@ -265,7 +268,9 @@ public class CashReportApiResource {
if (unsettled) {
try {
pendingAmount = denominationBreakdownWriter.getCashierTotalCash(cashierId);
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
}
// Check whether today's morning cash transfer has been received
@@ -276,7 +281,9 @@ public class CashReportApiResource {
Integer todayTransferCount = 0;
try {
todayTransferCount = jdbcTemplate.queryForObject(morningTransferSql, Integer.class, cashierId, today);
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
final boolean morningTransferReceived = todayTransferCount != null && todayTransferCount > 0;
result.put("cashierId", cashierId);
@@ -295,7 +302,7 @@ public class CashReportApiResource {
@Path("cashier-position")
public String cashierPosition(@QueryParam("cashierId") Long cashierId,
@QueryParam("asOfDate") String asOfDate) {
- final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now().toString();
+ final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
// CASHIER role: always scope to their own position only
final Long scopedId = cashierRoleHelper.getCashierIdForFiltering();
@@ -326,7 +333,7 @@ public class CashReportApiResource {
@GET
@Path("cashier-position/me")
public String cashierPositionMe(@QueryParam("asOfDate") String asOfDate) {
- final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now().toString();
+ final String dateFilter = (asOfDate != null && !asOfDate.isBlank()) ? asOfDate : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
Long appUserId;
try {
appUserId = context.authenticatedUser().getId();
@@ -362,7 +369,7 @@ public class CashReportApiResource {
@Path("cashier-morning")
public String cashierMorning(@QueryParam("cashierId") Long cashierId,
@QueryParam("date") String date) {
- final String txnDate = (date != null && !date.isBlank()) ? date : LocalDate.now().toString();
+ final String txnDate = (date != null && !date.isBlank()) ? date : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
if (cashierId == null) {
Map empty = new LinkedHashMap<>();
empty.put("cashierId", null);
@@ -515,7 +522,9 @@ public class CashReportApiResource {
cashierName = jdbcTemplate.queryForObject(
"SELECT ms.display_name FROM m_cashiers mc JOIN m_staff ms ON ms.id = mc.staff_id WHERE mc.id = ?",
String.class, cashierId);
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
Map result = new LinkedHashMap<>();
result.put("cashierId", cashierId);
@@ -562,7 +571,7 @@ public class CashReportApiResource {
@QueryParam("offset") Integer offset,
@QueryParam("limit") Integer limit) {
- final String txnDate = (date != null && !date.isBlank()) ? date : LocalDate.now().toString();
+ final String txnDate = (date != null && !date.isBlank()) ? date : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
final int resolvedLimit = (limit != null && limit > 0) ? limit : 20;
final int resolvedOffset = (offset != null && offset >= 0) ? offset : 0;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashsettlement/api/CashSettlementApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashsettlement/api/CashSettlementApiResource.java
index a9b8b64d9..90007a91a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashsettlement/api/CashSettlementApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashsettlement/api/CashSettlementApiResource.java
@@ -36,6 +36,7 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Path("/v1/cashsettlement")
@Component
@@ -70,7 +71,7 @@ public class CashSettlementApiResource {
}
final LocalDate settlementDate = json.has("settlementDate") && !json.get("settlementDate").isJsonNull()
- ? LocalDate.parse(json.get("settlementDate").getAsString()) : LocalDate.now();
+ ? LocalDate.parse(json.get("settlementDate").getAsString()) : LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
final String fromParty = json.has("fromParty") && !json.get("fromParty").isJsonNull()
? json.get("fromParty").getAsString() : null;
final String toParty = json.has("toParty") && !json.get("toParty").isJsonNull()
@@ -116,13 +117,15 @@ public class CashSettlementApiResource {
header.setToParty(toParty);
header.setSettlementAmount(total);
header.setNote(note);
- header.setCreatedAt(LocalDateTime.now());
+ header.setCreatedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
header.setIsReversed(false);
try {
AppUser user = this.context.authenticatedUser();
header.setPerformedBy(user.getId());
header.setPerformedByUsername(user.getUsername());
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
// Commit header + details first, then GL dispatch separately to avoid
// EclipseLink flushing pending detail rows inside Fineract's GL transaction.
@@ -142,7 +145,9 @@ public class CashSettlementApiResource {
Long resolved = jdbcTemplate.queryForObject(
"SELECT teller_id FROM m_cashiers WHERE id = ?", Long.class, fromCashierId);
if (resolved != null) glTellerId = resolved;
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
glDispatchService.settleCashFromCashier(glTellerId, fromCashierId, total,
currencyCode, settlementDate.format(DateTimeFormatter.ISO_LOCAL_DATE),
note != null ? note : "");
@@ -174,13 +179,17 @@ public class CashSettlementApiResource {
try {
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
reason = json.has("reason") ? json.get("reason").getAsString() : null;
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
AppUser user = null;
- try { user = this.context.authenticatedUser(); } catch (Exception ignored) {}
+ try { user = this.context.authenticatedUser(); } catch (Exception ignored) {
+ // intentionally ignored
+ }
settlement.setIsReversed(true);
- settlement.setReversedAt(LocalDateTime.now());
+ settlement.setReversedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
settlement.setReverseReason(reason);
if (user != null) settlement.setReversedBy(user.getId());
repository.save(settlement);
@@ -192,12 +201,16 @@ public class CashSettlementApiResource {
Long resolved = jdbcTemplate.queryForObject(
"SELECT teller_id FROM m_cashiers WHERE id = ?", Long.class, settlement.getFromCashierId());
if (resolved != null) glTellerId = resolved;
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
glDispatchService.allocateCashToCashier(glTellerId,
settlement.getFromCashierId(), settlement.getSettlementAmount(), "INR",
- LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE),
+ LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ISO_LOCAL_DATE),
"Reversal of cash settlement #" + id + (reason != null ? ": " + reason : ""));
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
}
JsonObject result = new JsonObject();
@@ -214,7 +227,7 @@ public class CashSettlementApiResource {
throw new PlatformDataIntegrityException("error.msg.cashsettlement.cashier.required",
"cashierId query param is required.");
}
- final String settlementDate = (date != null && !date.isBlank()) ? date : LocalDate.now().toString();
+ final String settlementDate = (date != null && !date.isBlank()) ? date : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
Integer count = jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM m_cash_settlement WHERE from_cashier_id = ? AND settlement_date = CAST(? AS DATE) AND (is_reversed IS NULL OR is_reversed = false)",
Integer.class, cashierId, settlementDate);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashTransferApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashTransferApiResource.java
index 359aad652..615b0623e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashTransferApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashTransferApiResource.java
@@ -36,6 +36,7 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Path("/v1/cashtransfer")
@Component
@@ -105,7 +106,7 @@ public class CashTransferApiResource {
header.setToCashierId(toCashierId);
header.setTransferAmount(total);
header.setNote(note);
- header.setCreatedAt(LocalDateTime.now());
+ header.setCreatedAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
try {
AppUser user = this.context.authenticatedUser();
if (user != null) {
@@ -136,8 +137,10 @@ public class CashTransferApiResource {
Long resolved = jdbcTemplate.queryForObject(
"SELECT teller_id FROM m_cashiers WHERE id = ?", Long.class, toCashierId);
if (resolved != null) glTellerId = resolved;
- } catch (Exception ignored) {}
- final LocalDate txnDate = transferDate != null ? transferDate : LocalDate.now();
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
+ final LocalDate txnDate = transferDate != null ? transferDate : LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
glDispatchService.allocateCashToCashier(glTellerId, toCashierId, total,
currencyCode, txnDate.format(DateTimeFormatter.ISO_LOCAL_DATE),
note != null ? note : "");
@@ -169,15 +172,19 @@ public class CashTransferApiResource {
try {
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
reason = json.has("reason") ? json.get("reason").getAsString() : null;
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
try {
AppUser user = this.context.authenticatedUser();
transfer.setReversedBy(user.getId());
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
transfer.setIsReversed(true);
- transfer.setReversedAt(java.time.LocalDateTime.now());
+ transfer.setReversedAt(java.time.LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
transfer.setReverseReason(reason);
repository.save(transfer);
@@ -188,12 +195,16 @@ public class CashTransferApiResource {
Long resolved = jdbcTemplate.queryForObject(
"SELECT teller_id FROM m_cashiers WHERE id = ?", Long.class, transfer.getToCashierId());
if (resolved != null) glTellerId = resolved;
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
glDispatchService.settleCashFromCashier(glTellerId,
transfer.getToCashierId(), transfer.getTransferAmount(), "INR",
- java.time.LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE),
+ java.time.LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ISO_LOCAL_DATE),
"Reversal of cash transfer #" + id + (reason != null ? ": " + reason : ""));
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ // intentionally ignored
+ }
}
JsonObject result = new JsonObject();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashierGlDenominationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashierGlDenominationApiResource.java
index 57e7d361a..002638999 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashierGlDenominationApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/CashierGlDenominationApiResource.java
@@ -38,6 +38,7 @@ import org.apache.fineract.portfolio.denominationmaster.domain.SavingsTxnDenomin
import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Records cashier denomination breakdown for GL account transactions (journal entries).
@@ -90,7 +91,7 @@ public class CashierGlDenominationApiResource {
final String txnDateStr = fromJsonHelper.extractStringNamed("txnDate", root);
final LocalDate txnDate = (txnDateStr != null && !txnDateStr.isBlank())
? LocalDate.parse(txnDateStr)
- : LocalDate.now();
+ : LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
if (!fromJsonHelper.parameterExists("denominationBreakdown", root)) {
return "{\"result\":\"skipped\"}";
@@ -109,7 +110,9 @@ public class CashierGlDenominationApiResource {
officerId = user.getId();
officerUsername = user.getUsername();
}
- } catch (final Exception ignored) {}
+ } catch (final Exception ignored) {
+ // intentionally ignored
+ }
final String resolvedTxnType = (txnType != null && !txnType.isBlank())
? txnType.toUpperCase()
@@ -144,7 +147,7 @@ public class CashierGlDenominationApiResource {
.count(count)
.totalAmount(lineTotal)
.txnDate(txnDate)
- .createdAt(LocalDateTime.now())
+ .createdAt(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()))
.txnType(resolvedTxnType)
.officerId(officerId)
.officerUsername(officerUsername)
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/ShareCollectionApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/ShareCollectionApiResource.java
index c59def7ee..5e7d9c977 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/ShareCollectionApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashtransfer/api/ShareCollectionApiResource.java
@@ -29,6 +29,7 @@ import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Cashier Share Collection API — POST /v1/cashier/sharecollection
@@ -131,7 +132,7 @@ public class ShareCollectionApiResource {
final LocalDate entryDate;
try {
entryDate = transactionDateStr != null
- ? LocalDate.parse(transactionDateStr) : LocalDate.now();
+ ? LocalDate.parse(transactionDateStr) : LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
} catch (DateTimeParseException e) {
throw new PlatformDataIntegrityException(
"error.msg.sharecollection.date.invalid",
@@ -193,7 +194,7 @@ public class ShareCollectionApiResource {
final String txnId = "SC-" + shareAccountId + "-" + System.currentTimeMillis();
final long userId = currentUser.getId();
final String collectorName = currentUser.getUsername();
- final LocalDateTime now = LocalDateTime.now();
+ final LocalDateTime now = LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant());
// ── Post GL journal entries ────────────────────────────────────────
// Dr Cash at Vault (SHARES_REFERENCE) = totalAmount
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsComplaintApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsComplaintApiResource.java
index 3daf73e02..55ae18e7b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsComplaintApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsComplaintApiResource.java
@@ -41,7 +41,6 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.cfcfrms.data.ComplaintStatsData;
import org.apache.fineract.portfolio.cfcfrms.data.ComplaintTicketData;
-import org.apache.fineract.portfolio.cfcfrms.data.TimelineEventData;
import org.apache.fineract.portfolio.cfcfrms.service.CfcfrmsComplaintService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsSimulatorApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsSimulatorApiResource.java
index a64fecca5..25674bc53 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsSimulatorApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/api/CfcfrmsSimulatorApiResource.java
@@ -56,7 +56,7 @@ import org.springframework.stereotype.Component;
* POST /v1/simulator/cfcfrms/verify-account – Verify account at bank
* POST /v1/simulator/cfcfrms/verify-transaction – Verify transaction ref
*
- * --- STATUS & REPORTING ---
+ * --- STATUS & REPORTING ---
* GET /v1/simulator/cfcfrms/complaint-status/{ref} – Complaint status from CFCFRMS side
* GET /v1/simulator/cfcfrms/bank-performance – Bank performance metrics
*
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/seed/CfcfrmsDataSeeder.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/seed/CfcfrmsDataSeeder.java
index 851e9e734..febad64b7 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/seed/CfcfrmsDataSeeder.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/seed/CfcfrmsDataSeeder.java
@@ -36,6 +36,7 @@ import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
/**
* Seeds CFCFRMS complaint tickets, audit logs, and simulator logs on startup.
@@ -59,7 +60,7 @@ public class CfcfrmsDataSeeder {
}
LOG.info("Seeding CFCFRMS complaint data...");
- final OffsetDateTime now = OffsetDateTime.now();
+ final OffsetDateTime now = OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant());
// ─── 3 RECEIVED ──────────────────────────────────────────────
seedTicket("TKT-20250318-001", "Rajesh Kumar Sharma", "9876543210",
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsComplaintServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsComplaintServiceImpl.java
index 378f0eb35..1ebe927b3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsComplaintServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsComplaintServiceImpl.java
@@ -46,6 +46,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Service
@RequiredArgsConstructor
@@ -206,7 +207,7 @@ public class CfcfrmsComplaintServiceImpl implements CfcfrmsComplaintService {
final Map result = new HashMap<>();
result.put("escalatedTo", nextIfsc);
result.put("escalationRef", escalationRef);
- result.put("timestamp", OffsetDateTime.now().toString());
+ result.put("timestamp", OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()).toString());
return result;
}
@@ -218,7 +219,7 @@ public class CfcfrmsComplaintServiceImpl implements CfcfrmsComplaintService {
}
private String generateTicketId() {
- final String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+ final String date = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
final int seq = (int) (ticketRepository.count() + 1);
return String.format("TKT-%s-%03d", date, seq);
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsSimulatorServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsSimulatorServiceImpl.java
index 20f2d1175..879f1c980 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsSimulatorServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cfcfrms/service/CfcfrmsSimulatorServiceImpl.java
@@ -25,12 +25,10 @@ import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
-import java.util.UUID;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.portfolio.cfcfrms.data.CfcfrmsConstants;
@@ -44,6 +42,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Service
@RequiredArgsConstructor
@@ -76,7 +75,7 @@ public class CfcfrmsSimulatorServiceImpl implements CfcfrmsSimulatorService {
final Map response = new LinkedHashMap<>();
response.put("cfcfrmsRef", cfcfrmsRef);
response.put("ticketId", ticketData.getTicketId());
- response.put("pushedToBankAt", OffsetDateTime.now().toString());
+ response.put("pushedToBankAt", OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()).toString());
response.put("bankAcknowledged", true);
response.put("message", "Complaint pushed to " + CfcfrmsConstants.BANK_IFSC + " successfully");
return response;
@@ -85,7 +84,7 @@ public class CfcfrmsSimulatorServiceImpl implements CfcfrmsSimulatorService {
@Override
public Map pushHoldDirective(final JsonObject json) {
final String cfcfrmsRef = getStringOrThrow(json, "cfcfrmsRef");
- final String directiveRef = "DIR-" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
+ final String directiveRef = "DIR-" + LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("yyyyMMdd"))
+ "-" + String.format("%04d", RANDOM.nextInt(10000));
final String directiveType = getStringOrThrow(json, "directiveType");
@@ -112,7 +111,7 @@ public class CfcfrmsSimulatorServiceImpl implements CfcfrmsSimulatorService {
response.put("directiveRef", directiveRef);
response.put("status", "DIRECTIVE_SENT");
response.put("bankResponse", bankResponse);
- response.put("timestamp", OffsetDateTime.now().toString());
+ response.put("timestamp", OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()).toString());
return response;
}
@@ -208,7 +207,7 @@ public class CfcfrmsSimulatorServiceImpl implements CfcfrmsSimulatorService {
public Map receiveEscalation(final JsonObject json) {
final String cfcfrmsRef = getStringOrThrow(json, "cfcfrmsRef");
final String ticketId = getStringOrThrow(json, "ticketId");
- final String escalationRef = "ESC-" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MMdd"))
+ final String escalationRef = "ESC-" + LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("yyyy-MMdd"))
+ "-" + String.format("%04d", RANDOM.nextInt(10000));
// Extract nextBank from fundsMovedTo
@@ -268,7 +267,7 @@ public class CfcfrmsSimulatorServiceImpl implements CfcfrmsSimulatorService {
final Map response = new LinkedHashMap<>();
response.put("transactionFound", true);
response.put("transactionStatus", "COMPLETED");
- response.put("transactionTimestamp", OffsetDateTime.now().minusHours(2).toString());
+ response.put("transactionTimestamp", OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()).minusHours(2).toString());
response.put("senderAccount", json.has("accountNumber") ? json.get("accountNumber").getAsString() : "UNKNOWN");
response.put("receiverAccount", json.has("accountNumber") ? json.get("accountNumber").getAsString() : "UNKNOWN");
@@ -369,14 +368,14 @@ public class CfcfrmsSimulatorServiceImpl implements CfcfrmsSimulatorService {
.setScale(1, java.math.RoundingMode.HALF_UP) + "%"
: "0.0%";
response.put("tatComplianceRate", tatCompliance);
- response.put("lastActivityAt", OffsetDateTime.now().toString());
+ response.put("lastActivityAt", OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant()).toString());
return response;
}
// ── Helpers ──
private String generateCfcfrmsRef() {
- final String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MMdd"));
+ final String date = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("yyyy-MMdd"));
return "CFCFRMS-" + date + "-" + String.format("%04d", RANDOM.nextInt(10000));
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/clearing/npci/service/NpciInwardPushService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/clearing/npci/service/NpciInwardPushService.java
index f6ae6838f..f3637cf92 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/clearing/npci/service/NpciInwardPushService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/clearing/npci/service/NpciInwardPushService.java
@@ -201,7 +201,7 @@ public class NpciInwardPushService {
final String presentingBranchCode = getString(instrument, "depositBranchCode");
item.recordInwardMeta(getString(instrument, "serialNumber"), presentingBranchCode, batch.getReturnTatDeadline());
- final Boolean instrumentStopPaymentFlag = instrument.has("stopPaymentFlag") && !instrument.get("stopPaymentFlag").isJsonNull()
+ final Boolean instrumentStopPaymentFlag = (instrument.has("stopPaymentFlag") && !instrument.get("stopPaymentFlag").isJsonNull())
? instrument.get("stopPaymentFlag").getAsBoolean()
: null;
item.recordSourceDetails(getString(instrument, "ctsReferenceNumber"), instrumentStopPaymentFlag,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkdisbursement/api/ClerkDisbursementRequestApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkdisbursement/api/ClerkDisbursementRequestApiResource.java
index ad8d054c7..bbea5abf1 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkdisbursement/api/ClerkDisbursementRequestApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkdisbursement/api/ClerkDisbursementRequestApiResource.java
@@ -70,6 +70,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
@Path("/v1/clerk/disbursement-requests")
@Component
@@ -383,7 +384,7 @@ public class ClerkDisbursementRequestApiResource {
final JsonArray creditEntries = gson.fromJson(creditEntriesJson, JsonArray.class);
final Object ptId = record.get("payment_type_id");
final String description = (String) record.get("description");
- final String txnDateStr = LocalDate.now().toString();
+ final String txnDateStr = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).toString();
final Long sourceGlId = record.get("gl_account_id") != null
? ((Number) record.get("gl_account_id")).longValue() : null;
@@ -556,7 +557,7 @@ public class ClerkDisbursementRequestApiResource {
final String entryType = entry.has("accountType") ? entry.get("accountType").getAsString() : "SAVINGS";
final String acNo = entry.has("accountNo") ? entry.get("accountNo").getAsString() : "?";
final Long entryPtId = entry.has("paymentTypeId") && !entry.get("paymentTypeId").isJsonNull()
- ? entry.get("paymentTypeId").getAsLong()
+ ? Long.valueOf(entry.get("paymentTypeId").getAsLong())
: (ptId != null ? ((Number) ptId).longValue() : null);
if ("GL".equals(entryType)) {
@@ -810,7 +811,7 @@ public class ClerkDisbursementRequestApiResource {
? req.get("currencyCode").getAsString() : "INR";
final String txnDateStr = req.has("transactionDate") && !req.get("transactionDate").isJsonNull()
? req.get("transactionDate").getAsString()
- : LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
+ : LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ISO_LOCAL_DATE);
final String description = req.has("description") && !req.get("description").isJsonNull()
? req.get("description").getAsString() : null;
@@ -830,7 +831,6 @@ public class ClerkDisbursementRequestApiResource {
// Validate all entries: savings/current only (no GL), savingsAccountId present, amount > 0
final Set drAccountIds = new LinkedHashSet<>();
- final Set crAccountIds = new LinkedHashSet<>();
for (final JsonObject e : drEntries) {
final String acTyp = e.has("accountType") ? e.get("accountType").getAsString() : "SAVINGS";
@@ -858,7 +858,6 @@ public class ClerkDisbursementRequestApiResource {
if (drAccountIds.contains(crId)) throw apiError(400,
"Account " + (e.has("accountNo") ? e.get("accountNo").getAsString() : crId)
+ " cannot appear on both DR and CR sides of the same transfer.");
- crAccountIds.add(crId);
}
// Validate balanced entry: total DR == total CR
@@ -999,7 +998,7 @@ public class ClerkDisbursementRequestApiResource {
* under concurrent inserts on the same date.
*/
private String generateBtVoucherNo(final long logId) {
- return "BT" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"))
+ return "BT" + LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("yyMMdd"))
+ String.format("%05d", logId);
}
@@ -1053,7 +1052,9 @@ public class ClerkDisbursementRequestApiResource {
try {
final Long txnIdLong = Long.parseLong(txnId);
undoOps.add(() -> undoAccountTransaction(accountId, txnIdLong, isCurrentAccount));
- } catch (NumberFormatException ignored) {}
+ } catch (NumberFormatException ignored) {
+ // intentionally ignored
+ }
}
private void undoAccountTransaction(final Long accountId, final Long transactionId,
@@ -1072,50 +1073,6 @@ public class ClerkDisbursementRequestApiResource {
commandsSourceWritePlatformService.logCommandSource(cmd);
}
- private String executeSavingsDeposit(
- final Long savingsAccountId, final BigDecimal amount,
- final Long paymentTypeId, final String txnDateStr, final String note) {
-
- final String date = formatForFineract(txnDateStr);
- final JsonObject payload = new JsonObject();
- payload.addProperty("locale", "en");
- payload.addProperty("dateFormat", "dd MMMM yyyy");
- payload.addProperty("transactionDate", date);
- payload.addProperty("transactionAmount", amount);
- if (paymentTypeId != null) payload.addProperty("paymentTypeId", paymentTypeId);
- if (note != null && !note.isBlank()) payload.addProperty("note", note);
-
- final CommandWrapper cmd = new CommandWrapperBuilder()
- .savingsAccountDeposit(savingsAccountId)
- .withJson(payload.toString())
- .build();
- fineractRequestContextHolder.setAttribute(SynchronousCommandProcessingService.COMMAND_SOURCE_ID, null);
- final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(cmd);
- return result.getResourceId() != null ? result.getResourceId().toString() : null;
- }
-
- private String executeCurrentAccountDeposit(
- final Long currentAccountId, final BigDecimal amount,
- final Long paymentTypeId, final String txnDateStr, final String note) {
-
- final String date = formatForFineract(txnDateStr);
- final JsonObject payload = new JsonObject();
- payload.addProperty("locale", "en");
- payload.addProperty("dateFormat", "dd MMMM yyyy");
- payload.addProperty("transactionDate", date);
- payload.addProperty("transactionAmount", amount);
- if (paymentTypeId != null) payload.addProperty("paymentTypeId", paymentTypeId);
- if (note != null && !note.isBlank()) payload.addProperty("note", note);
-
- final CommandWrapper cmd = new CommandWrapperBuilder()
- .currentAccountDeposit(currentAccountId)
- .withJson(payload.toString())
- .build();
- fineractRequestContextHolder.setAttribute(SynchronousCommandProcessingService.COMMAND_SOURCE_ID, null);
- final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(cmd);
- return result.getResourceId() != null ? result.getResourceId().toString() : null;
- }
-
private boolean isCurrentAccountById(final Long accountId) {
try {
final Integer count = jdbcTemplate.queryForObject(
@@ -1131,7 +1088,7 @@ public class ClerkDisbursementRequestApiResource {
final LocalDate ld = LocalDate.parse(isoDate, DateTimeFormatter.ISO_LOCAL_DATE);
return ld.format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
} catch (Exception e) {
- return LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ return LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
}
}
@@ -1380,7 +1337,7 @@ public class ClerkDisbursementRequestApiResource {
? (BigDecimal) accts.get(0).get("account_balance_derived") : BigDecimal.ZERO;
final java.sql.Date sqlDate = java.sql.Date.valueOf(txnDate);
- final OffsetDateTime now = OffsetDateTime.now();
+ final OffsetDateTime now = OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant());
final String refNo = UUID.randomUUID().toString().replace("-", "").substring(0, 20);
final Long userId = currentUser.getId();
@@ -1534,7 +1491,7 @@ public class ClerkDisbursementRequestApiResource {
+ ". Available: " + currentBalance + ", Requested: " + amount);
final java.sql.Date sqlDate = java.sql.Date.valueOf(txnDate);
- final OffsetDateTime now = OffsetDateTime.now();
+ final OffsetDateTime now = OffsetDateTime.now(DateUtils.getDateTimeZoneOfTenant());
final String refNo = UUID.randomUUID().toString().replace("-", "").substring(0, 20);
final Long userId = currentUser.getId();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkwithdrawal/api/ClerkWithdrawalRequestApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkwithdrawal/api/ClerkWithdrawalRequestApiResource.java
index bd7055cc6..813e80602 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkwithdrawal/api/ClerkWithdrawalRequestApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/clerkwithdrawal/api/ClerkWithdrawalRequestApiResource.java
@@ -59,6 +59,9 @@ import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import com.google.common.collect.Iterables;
+import com.google.common.base.Splitter;
@Path("/v1/clerk/withdrawal-requests")
@Component
@@ -437,7 +440,7 @@ public class ClerkWithdrawalRequestApiResource {
final BigDecimal amount = new BigDecimal(record.get("amount").toString());
final Object ptId = record.get("payment_type_id");
final Object txnDateObj = record.get("txn_date");
- final String txnDateStr = txnDateObj != null ? txnDateObj.toString().split(" ")[0] : null;
+ final String txnDateStr = txnDateObj != null ? Iterables.get(Splitter.on(' ').split(txnDateObj.toString()), 0) : null;
final String description = (String) record.get("description");
String txnId = null;
@@ -713,7 +716,7 @@ public class ClerkWithdrawalRequestApiResource {
final Long savingsAccountId, final BigDecimal amount,
final Object paymentTypeId, final String txnDateStr, final String note) {
- final String today = LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ final String today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
final String date = txnDateStr != null && !txnDateStr.isBlank() ? formatForFineract(txnDateStr) : today;
final JsonObject payload = new JsonObject();
@@ -741,7 +744,7 @@ public class ClerkWithdrawalRequestApiResource {
final Long currentAccountId, final BigDecimal amount,
final Object paymentTypeId, final String txnDateStr, final String note) {
- final String today = LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ final String today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
final String date = txnDateStr != null && !txnDateStr.isBlank() ? formatForFineract(txnDateStr) : today;
final JsonObject payload = new JsonObject();
@@ -780,7 +783,7 @@ public class ClerkWithdrawalRequestApiResource {
final LocalDate ld = LocalDate.parse(isoDate, DateTimeFormatter.ISO_LOCAL_DATE);
return ld.format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
} catch (Exception e) {
- return LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
+ return LocalDate.now(DateUtils.getDateTimeZoneOfTenant()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientKycApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientKycApiResource.java
index 46d5add4b..9b406eec8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientKycApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientKycApiResource.java
@@ -39,6 +39,8 @@ import jakarta.ws.rs.core.MediaType;
import java.io.InputStream;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
+import java.time.LocalDate;
+import java.time.Period;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -158,7 +160,13 @@ public class ClientKycApiResource {
template.put("clientTypeName", clientTypeName);
template.put("legalFormId", legalFormId);
- template.put("requiredDocuments", getRequiredDocuments(clientTypeName, legalFormId));
+ // Minor detection mirrors the frontend's own rule (age < 10) so the document list
+ // served here stays consistent with what the UI computes from the same date of birth.
+ final LocalDate dateOfBirth = client.dateOfBirth();
+ final boolean isMinor = dateOfBirth != null && Period.between(dateOfBirth, LocalDate.now()).getYears() < 10;
+ template.put("isMinor", isMinor);
+
+ template.put("requiredDocuments", getRequiredDocuments(clientTypeName, legalFormId, isMinor));
return toApiJsonSerializer.serialize(template);
}
@@ -166,11 +174,21 @@ public class ClientKycApiResource {
/**
* Returns required KYC documents based on client type (RBI Master Direction on KYC).
*/
- private List