add KYC document renewal alerts, Aadhaar/PAN exceptions, and AML recurring alerts UI; remove old journal AML marking
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
This commit is contained in:
+59
-4
@@ -98,6 +98,7 @@ import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.exception.SavingsAccountChargeNotFoundException;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientKyc;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
@@ -674,7 +675,7 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
|
||||
}
|
||||
|
||||
private boolean isWithHoldTaxApplicableForInterestPosting() {
|
||||
return this.withHoldTax() && this.depositAccountType().isSavingsDeposit();
|
||||
return false;
|
||||
}
|
||||
|
||||
protected SavingsAccountTransaction findInterestPostingTransactionFor(final LocalDate postingDate) {
|
||||
@@ -715,10 +716,65 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private Map<TaxComponent, BigDecimal> calculateTaxSplit(final BigDecimal amount, final LocalDate date, final int scale) {
|
||||
if (this.taxGroup == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
ClientKyc kyc = this.client != null ? this.client.getClientKyc() : null;
|
||||
|
||||
// 1. Form 15G/15H Waiver Check
|
||||
boolean waiveTds = false;
|
||||
if (kyc != null && Boolean.TRUE.equals(kyc.getForm15Applicable())) {
|
||||
String fy = kyc.getForm15Fy();
|
||||
if (isDateInFinancialYear(date, fy)) {
|
||||
waiveTds = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (waiveTds) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
// 2. Determine if 20% higher rate applies (missing/unlinked PAN)
|
||||
boolean applyHigherTdsRate = false;
|
||||
if (kyc != null) {
|
||||
boolean hasVerifiedPan = kyc.isPanVerified() || Boolean.TRUE.equals(kyc.getPanDeclarationTaken());
|
||||
String seedingStatus = kyc.getPanAadhaarSeedingStatus();
|
||||
|
||||
if (!hasVerifiedPan || "N".equalsIgnoreCase(seedingStatus)) {
|
||||
applyHigherTdsRate = true;
|
||||
}
|
||||
} else {
|
||||
// Default to higher rate (20%) if no KYC record is found
|
||||
applyHigherTdsRate = true;
|
||||
}
|
||||
|
||||
// 3. Split tax
|
||||
if (applyHigherTdsRate) {
|
||||
return TaxUtils.splitTaxWithOverride(amount, date, this.taxGroup.getTaxGroupMappings(), scale, new BigDecimal("20.00"));
|
||||
} else {
|
||||
return TaxUtils.splitTax(amount, date, this.taxGroup.getTaxGroupMappings(), scale);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDateInFinancialYear(final LocalDate date, final String fy) {
|
||||
if (fy == null || !fy.matches("\\d{4}-\\d{2}")) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
int startYear = Integer.parseInt(fy.substring(0, 4));
|
||||
LocalDate start = LocalDate.of(startYear, 4, 1);
|
||||
LocalDate end = LocalDate.of(startYear + 1, 3, 31);
|
||||
return !date.isBefore(start) && !date.isAfter(end);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean createWithHoldTransaction(final BigDecimal amount, final LocalDate date, final boolean backdatedTxnsAllowedTill) {
|
||||
boolean isTaxAdded = false;
|
||||
if (this.taxGroup != null && amount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
Map<TaxComponent, BigDecimal> taxSplit = TaxUtils.splitTax(amount, date, this.taxGroup.getTaxGroupMappings(), amount.scale());
|
||||
Map<TaxComponent, BigDecimal> taxSplit = calculateTaxSplit(amount, date, amount.scale());
|
||||
BigDecimal totalTax = TaxUtils.totalTaxAmount(taxSplit);
|
||||
if (totalTax.compareTo(BigDecimal.ZERO) > 0) {
|
||||
SavingsAccountTransaction withholdTransaction = SavingsAccountTransaction.withHoldTax(this, office(), date,
|
||||
@@ -737,8 +793,7 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
|
||||
protected boolean updateWithHoldTransaction(final BigDecimal amount, final SavingsAccountTransaction withholdTransaction) {
|
||||
boolean isTaxAdded = false;
|
||||
if (this.taxGroup != null && amount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
Map<TaxComponent, BigDecimal> taxSplit = TaxUtils.splitTax(amount, withholdTransaction.getTransactionDate(),
|
||||
this.taxGroup.getTaxGroupMappings(), amount.scale());
|
||||
Map<TaxComponent, BigDecimal> taxSplit = calculateTaxSplit(amount, withholdTransaction.getTransactionDate(), amount.scale());
|
||||
BigDecimal totalTax = TaxUtils.totalTaxAmount(taxSplit);
|
||||
if (totalTax.compareTo(BigDecimal.ZERO) > 0) {
|
||||
if (withholdTransaction.getId() == null) {
|
||||
|
||||
+1
@@ -54,6 +54,7 @@
|
||||
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
|
||||
<class>org.apache.fineract.portfolio.group.domain.Group</class>
|
||||
<class>org.apache.fineract.portfolio.client.domain.Client</class>
|
||||
<class>org.apache.fineract.portfolio.client.domain.ClientKyc</class>
|
||||
<class>org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration</class>
|
||||
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
|
||||
<class>org.apache.fineract.portfolio.paymenttype.domain.PaymentType</class>
|
||||
|
||||
Reference in New Issue
Block a user