implemented the Edit prodict functionality for the RD,FD,DDS,LIC
This commit is contained in:
+2
-2
@@ -113,7 +113,7 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer {
|
||||
final Long incomeFromRecoveryAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.INCOME_FROM_RECOVERY.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LoanProductAccountingParams.INCOME_FROM_RECOVERY.getValue())
|
||||
.value(incomeFromRecoveryAccountId).notNull().integerGreaterThanZero();
|
||||
.value(incomeFromRecoveryAccountId).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long writeOffAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
@@ -128,7 +128,7 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer {
|
||||
final Long transfersInSuspenseAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue())
|
||||
.value(transfersInSuspenseAccountId).notNull().integerGreaterThanZero();
|
||||
.value(transfersInSuspenseAccountId).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
}
|
||||
|
||||
|
||||
+13
-3
@@ -46,17 +46,27 @@ public class DelinquencyRange extends AbstractAuditableWithUTCDateTimeCustom<Lon
|
||||
@Column(name = "max_age_days", nullable = true)
|
||||
private Integer maximumAgeDays;
|
||||
|
||||
/**
|
||||
* Which ECL stage (1, 2 or 3) this range maps to under the RBI 2026 Directions. Nullable for ranges created
|
||||
* before this column existed; a range with no stage is treated as informational only and does not drive
|
||||
* staging or provisioning.
|
||||
*/
|
||||
@Column(name = "stage", nullable = true)
|
||||
private Integer stage;
|
||||
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
protected DelinquencyRange(@NotNull String classification, @NotNull Integer minimumAgeDays, Integer maximumAgeDays) {
|
||||
protected DelinquencyRange(@NotNull String classification, @NotNull Integer minimumAgeDays, Integer maximumAgeDays, Integer stage) {
|
||||
this.classification = classification;
|
||||
this.minimumAgeDays = minimumAgeDays;
|
||||
this.maximumAgeDays = maximumAgeDays;
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
public static DelinquencyRange instance(@NotNull String classification, @NotNull Integer minimumAge, Integer maximumAge) {
|
||||
return new DelinquencyRange(classification, minimumAge, maximumAge);
|
||||
public static DelinquencyRange instance(@NotNull String classification, @NotNull Integer minimumAge, Integer maximumAge,
|
||||
Integer stage) {
|
||||
return new DelinquencyRange(classification, minimumAge, maximumAge, stage);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
@@ -53,12 +53,20 @@ public class LoanProductToGLAccountMappingHelper extends ProductToGLAccountMappi
|
||||
paymentTypeRepositoryWrapper, codeValueRepository);
|
||||
}
|
||||
|
||||
/** Only the GLs the request names are mapped; the bank maps nine and leaves the other placeholders unmapped. */
|
||||
private boolean isMapped(final JsonElement element, final String paramName) {
|
||||
return this.fromApiJsonHelper.extractLongNamed(paramName, element) != null;
|
||||
}
|
||||
|
||||
/***
|
||||
* Set of abstractions for saving Loan Products to GL Account Mappings
|
||||
***/
|
||||
|
||||
public void saveLoanToAssetAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
if (!isMapped(element, paramName)) {
|
||||
return;
|
||||
}
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.ASSET, PortfolioProductType.LOAN);
|
||||
}
|
||||
|
||||
@@ -72,16 +80,25 @@ public class LoanProductToGLAccountMappingHelper extends ProductToGLAccountMappi
|
||||
|
||||
public void saveLoanToIncomeAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
if (!isMapped(element, paramName)) {
|
||||
return;
|
||||
}
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.INCOME, PortfolioProductType.LOAN);
|
||||
}
|
||||
|
||||
public void saveLoanToExpenseAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
if (!isMapped(element, paramName)) {
|
||||
return;
|
||||
}
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.EXPENSE, PortfolioProductType.LOAN);
|
||||
}
|
||||
|
||||
public void saveLoanToLiabilityAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
if (!isMapped(element, paramName)) {
|
||||
return;
|
||||
}
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.LIABILITY, PortfolioProductType.LOAN);
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ public final class DelinquencyApiConstants {
|
||||
public static final String RANGES_PARAM_NAME = "ranges";
|
||||
public static final String MINIMUMAGEDAYS_PARAM_NAME = "minimumAgeDays";
|
||||
public static final String MAXIMUMAGEDAYS_PARAM_NAME = "maximumAgeDays";
|
||||
public static final String STAGE_PARAM_NAME = "stage";
|
||||
public static final String LOCALE_PARAM_NAME = "locale";
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -35,5 +35,6 @@ public class DelinquencyRangeRequest implements Serializable {
|
||||
private String classification;
|
||||
private Integer minimumAgeDays;
|
||||
private Integer maximumAgeDays;
|
||||
private Integer stage;
|
||||
private String locale;
|
||||
}
|
||||
|
||||
+5
-3
@@ -34,13 +34,15 @@ public class DelinquencyRangeData implements Serializable {
|
||||
private String classification;
|
||||
private Integer minimumAgeDays;
|
||||
private Integer maximumAgeDays;
|
||||
/** ECL stage (1, 2 or 3) this range maps to under the RBI 2026 Directions; null on ranges predating this field. */
|
||||
private Integer stage;
|
||||
|
||||
public static DelinquencyRangeData instance(String classification, Integer minimumAgeDays, Integer maximumAgeDays) {
|
||||
return new DelinquencyRangeData(null, classification, minimumAgeDays, maximumAgeDays);
|
||||
public static DelinquencyRangeData instance(String classification, Integer minimumAgeDays, Integer maximumAgeDays, Integer stage) {
|
||||
return new DelinquencyRangeData(null, classification, minimumAgeDays, maximumAgeDays, stage);
|
||||
}
|
||||
|
||||
public static DelinquencyRangeData reference(Long id) {
|
||||
return new DelinquencyRangeData(id, "", 0, 0);
|
||||
return new DelinquencyRangeData(id, "", 0, 0, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-1
@@ -305,7 +305,7 @@ public class DelinquencyWritePlatformServiceImpl implements DelinquencyWritePlat
|
||||
throw new DelinquencyRangeInvalidAgesException(errorMessage, data.getMinimumAgeDays(), data.getMaximumAgeDays());
|
||||
}
|
||||
DelinquencyRange newDelinquencyRange = DelinquencyRange.instance(data.getClassification(), data.getMinimumAgeDays(),
|
||||
data.getMaximumAgeDays());
|
||||
data.getMaximumAgeDays(), data.getStage());
|
||||
return repositoryRange.saveAndFlush(newDelinquencyRange);
|
||||
} else {
|
||||
throw new PlatformDataIntegrityException("error.msg.data.integrity.issue.entity.duplicated",
|
||||
@@ -327,6 +327,10 @@ public class DelinquencyWritePlatformServiceImpl implements DelinquencyWritePlat
|
||||
delinquencyRange.setMaximumAgeDays(data.getMaximumAgeDays());
|
||||
changes.put(DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME, data.getMaximumAgeDays());
|
||||
}
|
||||
if (!java.util.Objects.equals(data.getStage(), delinquencyRange.getStage())) {
|
||||
delinquencyRange.setStage(data.getStage());
|
||||
changes.put(DelinquencyApiConstants.STAGE_PARAM_NAME, data.getStage());
|
||||
}
|
||||
if (!changes.isEmpty()) {
|
||||
delinquencyRange = repositoryRange.saveAndFlush(delinquencyRange);
|
||||
}
|
||||
|
||||
+5
-2
@@ -56,7 +56,8 @@ public class DelinquencyRangeParseAndValidator extends ParseAndValidator {
|
||||
|
||||
jsonHelper.checkForUnsupportedParameters(element,
|
||||
List.of(DelinquencyApiConstants.CLASSIFICATION_PARAM_NAME, DelinquencyApiConstants.MINIMUMAGEDAYS_PARAM_NAME,
|
||||
DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME, DelinquencyApiConstants.LOCALE_PARAM_NAME));
|
||||
DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME, DelinquencyApiConstants.STAGE_PARAM_NAME,
|
||||
DelinquencyApiConstants.LOCALE_PARAM_NAME));
|
||||
|
||||
final String localeValue = jsonHelper.extractStringNamed(DelinquencyApiConstants.LOCALE_PARAM_NAME, element);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.LOCALE_PARAM_NAME).value(localeValue).notBlank();
|
||||
@@ -65,13 +66,15 @@ public class DelinquencyRangeParseAndValidator extends ParseAndValidator {
|
||||
final String classification = jsonHelper.extractStringNamed(DelinquencyApiConstants.CLASSIFICATION_PARAM_NAME, element);
|
||||
final Integer minimumAge = jsonHelper.extractIntegerNamed(DelinquencyApiConstants.MINIMUMAGEDAYS_PARAM_NAME, element, locale);
|
||||
final Integer maximumAge = jsonHelper.extractIntegerNamed(DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME, element, locale);
|
||||
final Integer stage = jsonHelper.extractIntegerNamed(DelinquencyApiConstants.STAGE_PARAM_NAME, element, locale);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.CLASSIFICATION_PARAM_NAME).value(classification).notBlank();
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.MINIMUMAGEDAYS_PARAM_NAME).value(minimumAge).notBlank()
|
||||
.integerGreaterThanNumber(0);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME).value(maximumAge).ignoreIfNull()
|
||||
.integerGreaterThanNumber(0);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.STAGE_PARAM_NAME).value(stage).ignoreIfNull().inMinMaxRange(1, 3);
|
||||
|
||||
return dataValidator.hasError() ? null : DelinquencyRangeData.instance(classification, minimumAge, maximumAge);
|
||||
return dataValidator.hasError() ? null : DelinquencyRangeData.instance(classification, minimumAge, maximumAge, stage);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+62
@@ -137,6 +137,31 @@ public class LoanProductAdvanceExt {
|
||||
@Column(name = "npa_trigger")
|
||||
private String npaTrigger;
|
||||
|
||||
/** Months after disbursement before overdue days (SMA) start counting: Advances 9, Loans (EMI) 1. */
|
||||
@Column(name = "sma_start_after_months")
|
||||
private Integer smaStartAfterMonths;
|
||||
|
||||
/** CC/OD: stock statement older than this many days makes drawings an NPA trigger (RBI: 90). */
|
||||
@Column(name = "stock_statement_validity_days")
|
||||
private Integer stockStatementValidityDays;
|
||||
|
||||
// ---- common eligibility & document checklist (Advances and Loans) ----
|
||||
@Column(name = "elig_member_required")
|
||||
private Boolean memberRequired;
|
||||
|
||||
@Column(name = "elig_guarantor_must_be_member")
|
||||
private Boolean guarantorMustBeMember;
|
||||
|
||||
@Column(name = "elig_income_multiple")
|
||||
private BigDecimal incomeMultiple;
|
||||
|
||||
@Column(name = "elig_min_vintage_months")
|
||||
private Integer minVintageMonths;
|
||||
|
||||
/** Comma separated document codes the borrower must submit for this product. */
|
||||
@Column(name = "required_documents", length = 1000)
|
||||
private String requiredDocuments;
|
||||
|
||||
@Column(name = "interest_after_npa")
|
||||
private String interestAfterNpa;
|
||||
|
||||
@@ -464,6 +489,43 @@ public class LoanProductAdvanceExt {
|
||||
@Column(name = "loan_balance_transfer_out_allowed")
|
||||
private Boolean balanceTransferOutAllowed;
|
||||
|
||||
// ---- SICR & LGD (RBI 2026 ECL framework; floor % itself lives in the Prudential Floor master, not here) ----
|
||||
@Column(name = "sicr_days_threshold")
|
||||
private Integer sicrDaysThreshold;
|
||||
|
||||
@Column(name = "sicr_revolving_days_threshold")
|
||||
private Integer sicrRevolvingDaysThreshold;
|
||||
|
||||
@Column(name = "sicr_rating_downgrade_notches")
|
||||
private Integer sicrRatingDowngradeNotches;
|
||||
|
||||
@Column(name = "sicr_pricing_increase_trigger_pct")
|
||||
private BigDecimal sicrPricingIncreaseTriggerPct;
|
||||
|
||||
@Column(name = "sicr_assessment_basis")
|
||||
private String sicrAssessmentBasis;
|
||||
|
||||
@Column(name = "sicr_rebuttal_allowed")
|
||||
private Boolean sicrRebuttalAllowed;
|
||||
|
||||
@Column(name = "npa_out_of_order_basis")
|
||||
private String npaOutOfOrderBasis;
|
||||
|
||||
@Column(name = "crop_duration")
|
||||
private String cropDuration;
|
||||
|
||||
@Column(name = "use_own_lgd_model")
|
||||
private Boolean useOwnLgdModel;
|
||||
|
||||
@Column(name = "lgd_secured_pct")
|
||||
private BigDecimal lgdSecuredPct;
|
||||
|
||||
@Column(name = "lgd_unsecured_pct")
|
||||
private BigDecimal lgdUnsecuredPct;
|
||||
|
||||
@Column(name = "eligible_collateral_type")
|
||||
private String eligibleCollateralType;
|
||||
|
||||
public LoanProductAdvanceExt(final LoanProduct loanProduct) {
|
||||
this.loanProduct = loanProduct;
|
||||
this.loanProductId = loanProduct.getId();
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.prudentialfloor.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class PrudentialFloorData implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private String productCategory;
|
||||
private Integer stage;
|
||||
private Integer durationFromDays;
|
||||
private Integer durationToDays;
|
||||
private BigDecimal securedFloorPct;
|
||||
private BigDecimal unsecuredFloorPct;
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.prudentialfloor.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Version;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
|
||||
/**
|
||||
* One row of the RBI 2026 ECL "prudential floor" table (Directions para 82): the minimum provisioning percentage
|
||||
* a bank must hold for a given loan product category and stage. Seeded centrally from the regulation rather than
|
||||
* entered per product - a loan product only ever declares its category ({@code loanProductCategory} on
|
||||
* {@link org.apache.fineract.portfolio.loanproduct.domain.LoanProductAdvanceExt}) and its stage (via its
|
||||
* Delinquency Bucket); the applicable floor % is always looked up here, never duplicated onto the product or the
|
||||
* range.
|
||||
*
|
||||
* Stage 1 and Stage 2 rows apply regardless of duration ({@code durationFromDays}/{@code durationToDays} are
|
||||
* null and {@code securedFloorPct} equals {@code unsecuredFloorPct}, since the Directions do not split those two
|
||||
* stages by security). Stage 3 rows are further split by how long the exposure has been in Stage 3
|
||||
* ({@code durationToDays} null means "and beyond") and by secured/unsecured portion.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "m_prudential_floor")
|
||||
public class PrudentialFloor extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
|
||||
@Column(name = "product_category", nullable = false)
|
||||
private String productCategory;
|
||||
|
||||
/** 1, 2 or 3. */
|
||||
@Column(name = "stage", nullable = false)
|
||||
private Integer stage;
|
||||
|
||||
@Column(name = "duration_from_days", nullable = true)
|
||||
private Integer durationFromDays;
|
||||
|
||||
/** Null means open-ended ("after 4 years" etc.). */
|
||||
@Column(name = "duration_to_days", nullable = true)
|
||||
private Integer durationToDays;
|
||||
|
||||
@Column(name = "secured_floor_pct", nullable = false)
|
||||
private BigDecimal securedFloorPct;
|
||||
|
||||
@Column(name = "unsecured_floor_pct", nullable = false)
|
||||
private BigDecimal unsecuredFloorPct;
|
||||
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
private PrudentialFloor(@NotNull String productCategory, @NotNull Integer stage, Integer durationFromDays, Integer durationToDays,
|
||||
@NotNull BigDecimal securedFloorPct, @NotNull BigDecimal unsecuredFloorPct) {
|
||||
this.productCategory = productCategory;
|
||||
this.stage = stage;
|
||||
this.durationFromDays = durationFromDays;
|
||||
this.durationToDays = durationToDays;
|
||||
this.securedFloorPct = securedFloorPct;
|
||||
this.unsecuredFloorPct = unsecuredFloorPct;
|
||||
}
|
||||
|
||||
public static PrudentialFloor instance(@NotNull String productCategory, @NotNull Integer stage, Integer durationFromDays,
|
||||
Integer durationToDays, @NotNull BigDecimal securedFloorPct, @NotNull BigDecimal unsecuredFloorPct) {
|
||||
return new PrudentialFloor(productCategory, stage, durationFromDays, durationToDays, securedFloorPct, unsecuredFloorPct);
|
||||
}
|
||||
|
||||
/** True when {@code daysInStage} falls within this row's duration band (always true for a Stage 1/2 row). */
|
||||
public boolean coversDuration(Integer daysInStage) {
|
||||
if (this.durationFromDays == null) {
|
||||
return true;
|
||||
}
|
||||
if (daysInStage == null) {
|
||||
return false;
|
||||
}
|
||||
boolean aboveFrom = daysInStage >= this.durationFromDays;
|
||||
boolean belowTo = this.durationToDays == null || daysInStage <= this.durationToDays;
|
||||
return aboveFrom && belowTo;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.prudentialfloor.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface PrudentialFloorRepository extends JpaRepository<PrudentialFloor, Long> {
|
||||
|
||||
List<PrudentialFloor> findByProductCategoryAndStage(String productCategory, Integer stage);
|
||||
|
||||
List<PrudentialFloor> findByProductCategoryOrderByStageAscDurationFromDaysAsc(String productCategory);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.prudentialfloor.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.data.PrudentialFloorData;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.domain.PrudentialFloor;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
@Mapper(config = MapstructMapperConfig.class)
|
||||
public interface PrudentialFloorMapper {
|
||||
|
||||
PrudentialFloorData map(PrudentialFloor source);
|
||||
|
||||
List<PrudentialFloorData> map(List<PrudentialFloor> sources);
|
||||
}
|
||||
+11
@@ -79,6 +79,17 @@ public class MakercheckersApiResource {
|
||||
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/mine")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "List my pending Maker Checker Entries", description = "Requests the requestor submitted that still await approval. Unlike the checker inbox it needs no checker permission, so a maker can see what is pending. Example: makercheckers/mine?entityName=LOANPRODUCT")
|
||||
public List<AuditData> retrieveMyPendingCommands(@Context final UriInfo uriInfo, @BeanParam MakerCheckerRequest makerCheckerRequest) {
|
||||
final SQLBuilder extraCriteria = getExtraCriteria(makerCheckerRequest);
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return readPlatformService.retrieveMyPendingEntries(extraCriteria, settings.isIncludeJson());
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/searchtemplate")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
|
||||
+3
@@ -33,6 +33,9 @@ public interface AuditReadPlatformService {
|
||||
|
||||
List<AuditData> retrieveAllEntriesToBeChecked(SQLBuilder extraCriteria, boolean includeJson);
|
||||
|
||||
/** Requests the current user submitted that still await a checker, whatever the user's own checker permissions. */
|
||||
List<AuditData> retrieveMyPendingEntries(SQLBuilder extraCriteria, boolean includeJson);
|
||||
|
||||
AuditData retrieveAuditEntry(Long auditId);
|
||||
|
||||
AuditSearchData retrieveSearchTemplate(String useType);
|
||||
|
||||
+8
-1
@@ -214,10 +214,17 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
|
||||
return retrieveEntries("makerchecker", extraCriteria, " order by aud.id, mk.username", includeJson);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuditData> retrieveMyPendingEntries(final SQLBuilder extraCriteria, final boolean includeJson) {
|
||||
extraCriteria.addCriteria("aud.status = ", 2);
|
||||
extraCriteria.addCriteria("aud.maker_id = ", this.context.authenticatedUser().getId());
|
||||
return retrieveEntries("makerchecker-mine", extraCriteria, " order by aud.id, mk.username", includeJson);
|
||||
}
|
||||
|
||||
private List<AuditData> retrieveEntries(final String useType, final SQLBuilder extraCriteria, final String groupAndOrderBySQL,
|
||||
final boolean includeJson) {
|
||||
|
||||
if ((!useType.equals("audit") && !useType.equals("makerchecker"))) {
|
||||
if ((!useType.equals("audit") && !useType.equals("makerchecker") && !useType.equals("makerchecker-mine"))) {
|
||||
throw new PlatformDataIntegrityException("error.msg.invalid.auditSearchTemplate.useType",
|
||||
"Invalid Audit Search Template UseType: " + useType);
|
||||
}
|
||||
|
||||
+3
-2
@@ -679,8 +679,9 @@ public final class LoanProductDataValidator {
|
||||
|
||||
final Long transfersInSuspenseAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), element);
|
||||
// not mapped by the bank (only the nine GLs are); optional
|
||||
baseDataValidator.reset().parameter(LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue())
|
||||
.value(transfersInSuspenseAccountId).notNull().integerGreaterThanZero();
|
||||
.value(transfersInSuspenseAccountId).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromInterestId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.INTEREST_ON_LOANS.getValue(), element);
|
||||
@@ -700,7 +701,7 @@ public final class LoanProductDataValidator {
|
||||
final Long incomeFromRecoveryAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.INCOME_FROM_RECOVERY.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LoanProductAccountingParams.INCOME_FROM_RECOVERY.getValue())
|
||||
.value(incomeFromRecoveryAccountId).notNull().integerGreaterThanZero();
|
||||
.value(incomeFromRecoveryAccountId).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long writeOffAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
|
||||
+49
-2
@@ -43,7 +43,8 @@ public class LoanProductAdvanceExtService {
|
||||
"securityType", "chargeType", "eligibleAmountBasis", "margin", "ltv", "dpMethod", "lienRequired",
|
||||
"lienMarkingStage", "lienCertificateRequired", "lienCertificatePrefix", "printCertificateOnDisbursement",
|
||||
"interestBasis", "spread", "interestChargedOn", "interestPostingFrequency", "penalApplicable", "penalRate",
|
||||
"penalAppliedOn", "penalGraceDays", "npaTrigger", "interestAfterNpa", "undebitedInterestGlId",
|
||||
"penalAppliedOn", "penalGraceDays", "npaTrigger", "smaStartAfterMonths", "stockStatementValidityDays", "memberRequired", "guarantorMustBeMember",
|
||||
"incomeMultiple", "minVintageMonths", "requiredDocuments", "interestAfterNpa", "undebitedInterestGlId",
|
||||
"renewalAllowed", "renewalPeriodMonths", "renewalGraceDays", "preclosureAllowed", "lockInMonths",
|
||||
"interestOnPreclosure", "revaluationFreqMonths", "insuranceRequired", "stockStatementFreqMonths",
|
||||
"chequeBookEnabled", "chequeType", "defaultChequeBookSize", "ppsThreshold", "ppsMandatoryAbove",
|
||||
@@ -76,7 +77,11 @@ public class LoanProductAdvanceExtService {
|
||||
"partPrepaymentAllowed", "minPartPayment", "allowedOn", "partPaymentsPerYear",
|
||||
"partPrepaymentMode", "foreclosureFloatingIndividual", "foreclosureFixedIndividual", "foreclosureNonIndividual",
|
||||
"foreclosureTakeover", "foreclosureQuoteValidDays", "autoCloseOnZeroBalance", "nocLetter",
|
||||
"restructuring", "releaseCollateralOnClosure", "topUpAllowed", "balanceTransferOutAllowed" };
|
||||
"restructuring", "releaseCollateralOnClosure", "topUpAllowed", "balanceTransferOutAllowed",
|
||||
// SICR & LGD (RBI 2026 ECL framework)
|
||||
"sicrDaysThreshold", "sicrRevolvingDaysThreshold", "sicrRatingDowngradeNotches", "sicrPricingIncreaseTriggerPct",
|
||||
"sicrAssessmentBasis", "sicrRebuttalAllowed", "npaOutOfOrderBasis", "cropDuration", "useOwnLgdModel", "lgdSecuredPct",
|
||||
"lgdUnsecuredPct", "eligibleCollateralType" };
|
||||
|
||||
/**
|
||||
* Insert or partial-update the satellite for this product. Returns the fields that actually changed so the
|
||||
@@ -155,6 +160,14 @@ public class LoanProductAdvanceExtService {
|
||||
setString(command, "penalAppliedOn", ext::getPenalAppliedOn, ext::setPenalAppliedOn, changes);
|
||||
setInteger(command, "penalGraceDays", ext::getPenalGraceDays, ext::setPenalGraceDays, changes);
|
||||
setString(command, "npaTrigger", ext::getNpaTrigger, ext::setNpaTrigger, changes);
|
||||
setInteger(command, "smaStartAfterMonths", ext::getSmaStartAfterMonths, ext::setSmaStartAfterMonths, changes);
|
||||
setBoolean(command, "memberRequired", ext::getMemberRequired, ext::setMemberRequired, changes);
|
||||
setBoolean(command, "guarantorMustBeMember", ext::getGuarantorMustBeMember, ext::setGuarantorMustBeMember, changes);
|
||||
setDecimal(command, "incomeMultiple", ext::getIncomeMultiple, ext::setIncomeMultiple, changes);
|
||||
setInteger(command, "minVintageMonths", ext::getMinVintageMonths, ext::setMinVintageMonths, changes);
|
||||
setString(command, "requiredDocuments", ext::getRequiredDocuments, ext::setRequiredDocuments, changes);
|
||||
setInteger(command, "stockStatementValidityDays", ext::getStockStatementValidityDays,
|
||||
ext::setStockStatementValidityDays, changes);
|
||||
setString(command, "interestAfterNpa", ext::getInterestAfterNpa, ext::setInterestAfterNpa, changes);
|
||||
setLong(command, "undebitedInterestGlId", ext::getUndebitedInterestGlId, ext::setUndebitedInterestGlId, changes);
|
||||
setBoolean(command, "renewalAllowed", ext::getRenewalAllowed, ext::setRenewalAllowed, changes);
|
||||
@@ -289,6 +302,20 @@ public class LoanProductAdvanceExtService {
|
||||
setBoolean(command, "releaseCollateralOnClosure", ext::getReleaseCollateralOnClosure, ext::setReleaseCollateralOnClosure, changes);
|
||||
setBoolean(command, "topUpAllowed", ext::getTopUpAllowed, ext::setTopUpAllowed, changes);
|
||||
setBoolean(command, "balanceTransferOutAllowed", ext::getBalanceTransferOutAllowed, ext::setBalanceTransferOutAllowed, changes);
|
||||
// SICR & LGD (RBI 2026 ECL framework)
|
||||
setInteger(command, "sicrDaysThreshold", ext::getSicrDaysThreshold, ext::setSicrDaysThreshold, changes);
|
||||
setInteger(command, "sicrRevolvingDaysThreshold", ext::getSicrRevolvingDaysThreshold, ext::setSicrRevolvingDaysThreshold, changes);
|
||||
setInteger(command, "sicrRatingDowngradeNotches", ext::getSicrRatingDowngradeNotches, ext::setSicrRatingDowngradeNotches, changes);
|
||||
setDecimal(command, "sicrPricingIncreaseTriggerPct", ext::getSicrPricingIncreaseTriggerPct, ext::setSicrPricingIncreaseTriggerPct,
|
||||
changes);
|
||||
setString(command, "sicrAssessmentBasis", ext::getSicrAssessmentBasis, ext::setSicrAssessmentBasis, changes);
|
||||
setBoolean(command, "sicrRebuttalAllowed", ext::getSicrRebuttalAllowed, ext::setSicrRebuttalAllowed, changes);
|
||||
setString(command, "npaOutOfOrderBasis", ext::getNpaOutOfOrderBasis, ext::setNpaOutOfOrderBasis, changes);
|
||||
setString(command, "cropDuration", ext::getCropDuration, ext::setCropDuration, changes);
|
||||
setBoolean(command, "useOwnLgdModel", ext::getUseOwnLgdModel, ext::setUseOwnLgdModel, changes);
|
||||
setDecimal(command, "lgdSecuredPct", ext::getLgdSecuredPct, ext::setLgdSecuredPct, changes);
|
||||
setDecimal(command, "lgdUnsecuredPct", ext::getLgdUnsecuredPct, ext::setLgdUnsecuredPct, changes);
|
||||
setString(command, "eligibleCollateralType", ext::getEligibleCollateralType, ext::setEligibleCollateralType, changes);
|
||||
}
|
||||
|
||||
// ---- typed setters: only write params that are present, and only report real changes ----------
|
||||
@@ -403,6 +430,13 @@ public class LoanProductAdvanceExtService {
|
||||
map.put("penalAppliedOn", ext.getPenalAppliedOn());
|
||||
map.put("penalGraceDays", ext.getPenalGraceDays());
|
||||
map.put("npaTrigger", ext.getNpaTrigger());
|
||||
map.put("smaStartAfterMonths", ext.getSmaStartAfterMonths());
|
||||
map.put("memberRequired", ext.getMemberRequired());
|
||||
map.put("guarantorMustBeMember", ext.getGuarantorMustBeMember());
|
||||
map.put("incomeMultiple", ext.getIncomeMultiple());
|
||||
map.put("minVintageMonths", ext.getMinVintageMonths());
|
||||
map.put("requiredDocuments", ext.getRequiredDocuments());
|
||||
map.put("stockStatementValidityDays", ext.getStockStatementValidityDays());
|
||||
map.put("interestAfterNpa", ext.getInterestAfterNpa());
|
||||
map.put("undebitedInterestGlId", ext.getUndebitedInterestGlId());
|
||||
map.put("renewalAllowed", ext.getRenewalAllowed());
|
||||
@@ -509,6 +543,19 @@ public class LoanProductAdvanceExtService {
|
||||
map.put("releaseCollateralOnClosure", ext.getReleaseCollateralOnClosure());
|
||||
map.put("topUpAllowed", ext.getTopUpAllowed());
|
||||
map.put("balanceTransferOutAllowed", ext.getBalanceTransferOutAllowed());
|
||||
// SICR & LGD (RBI 2026 ECL framework)
|
||||
map.put("sicrDaysThreshold", ext.getSicrDaysThreshold());
|
||||
map.put("sicrRevolvingDaysThreshold", ext.getSicrRevolvingDaysThreshold());
|
||||
map.put("sicrRatingDowngradeNotches", ext.getSicrRatingDowngradeNotches());
|
||||
map.put("sicrPricingIncreaseTriggerPct", ext.getSicrPricingIncreaseTriggerPct());
|
||||
map.put("sicrAssessmentBasis", ext.getSicrAssessmentBasis());
|
||||
map.put("sicrRebuttalAllowed", ext.getSicrRebuttalAllowed());
|
||||
map.put("npaOutOfOrderBasis", ext.getNpaOutOfOrderBasis());
|
||||
map.put("cropDuration", ext.getCropDuration());
|
||||
map.put("useOwnLgdModel", ext.getUseOwnLgdModel());
|
||||
map.put("lgdSecuredPct", ext.getLgdSecuredPct());
|
||||
map.put("lgdUnsecuredPct", ext.getLgdUnsecuredPct());
|
||||
map.put("eligibleCollateralType", ext.getEligibleCollateralType());
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.prudentialfloor.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.data.PrudentialFloorData;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.service.PrudentialFloorReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Read-only: this master is seeded from the RBI 2026 Directions (para 82) rather than created per bank, so it
|
||||
* ships without a create/update command path for now - a Board-approved "tighten only" override is a follow-up.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Path("/v1/prudentialfloors")
|
||||
@Component
|
||||
@Tag(name = "Prudential Floor Master", description = "RBI 2026 ECL stage-wise prudential floor lookup, by loan product category")
|
||||
public class PrudentialFloorsApiResource {
|
||||
|
||||
private final PlatformSecurityContext securityContext;
|
||||
private final PrudentialFloorReadPlatformService readPlatformService;
|
||||
public static final String PRUDENTIAL_FLOOR = "PRUDENTIAL_FLOOR";
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "List all Prudential Floor rows", description = "Optionally filter by product category")
|
||||
public List<PrudentialFloorData> getPrudentialFloors(
|
||||
@QueryParam("productCategory") @Parameter(description = "productCategory") final String productCategory) {
|
||||
securityContext.authenticatedUser().validateHasReadPermission(PRUDENTIAL_FLOOR);
|
||||
if (productCategory == null || productCategory.isBlank()) {
|
||||
return this.readPlatformService.retrieveAll();
|
||||
}
|
||||
return this.readPlatformService.retrieveForCategory(productCategory);
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.prudentialfloor.service;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.data.PrudentialFloorData;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.domain.PrudentialFloor;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.domain.PrudentialFloorRepository;
|
||||
import org.apache.fineract.portfolio.prudentialfloor.mapper.PrudentialFloorMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Read-only lookup over the RBI 2026 prudential-floor master (para 82). A loan product never stores its own
|
||||
* floor %: it declares a product category and a stage (the latter via its Delinquency Bucket), and the
|
||||
* applicable floor is resolved here at reporting/provisioning time, so every product using the same category
|
||||
* always sees the same, currently-seeded regulatory minimum.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class PrudentialFloorReadPlatformService {
|
||||
|
||||
private final PrudentialFloorRepository repository;
|
||||
private final PrudentialFloorMapper mapper;
|
||||
|
||||
public List<PrudentialFloorData> retrieveAll() {
|
||||
return mapper.map(repository.findAll());
|
||||
}
|
||||
|
||||
public List<PrudentialFloorData> retrieveForCategory(final String productCategory) {
|
||||
return mapper.map(repository.findByProductCategoryOrderByStageAscDurationFromDaysAsc(productCategory));
|
||||
}
|
||||
|
||||
/**
|
||||
* The floor applicable to one exposure: for Stage 1/2 the single row for that category+stage; for Stage 3
|
||||
* the row whose duration band contains {@code daysInStage} (days since the exposure entered Stage 3, not
|
||||
* days overdue). Returns {@code null} when the category/stage/duration combination has not been seeded -
|
||||
* callers should fall back to the residual "any other loan product category" floor (para 82 item (xv)) in
|
||||
* that case rather than treat it as zero.
|
||||
*/
|
||||
public PrudentialFloorData retrieveFloor(final String productCategory, final Integer stage, final Integer daysInStage) {
|
||||
final List<PrudentialFloor> candidates = repository.findByProductCategoryAndStage(productCategory, stage);
|
||||
return candidates.stream().filter(row -> row.coversDuration(daysInStage)).findFirst().map(mapper::map).orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -623,6 +623,13 @@
|
||||
<include file="parts/0595_seed_loan_rate_register_gl_accounts.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0596_enable_delinquency_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0597_add_loan_product_loans_ext_fields.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0598_add_loan_product_sma_start_fields.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0599_enable_loan_product_update_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
|
||||
<!-- RBI 2026 ECL framework: SMA/NPA asset classification, prudential floor master, SICR/LGD product config. -->
|
||||
<include file="parts/0599_add_delinquency_range_stage.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0600_create_prudential_floor_master.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0601_add_loan_product_advance_ext_sicr_lgd_fields.xml" relativeToChangelogFile="true"/>
|
||||
|
||||
<!-- DDS: the scheme's own tables, settings and permissions. Kept together and last, because
|
||||
each one builds on the core the block above sets up and none of it builds on DDS. -->
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!-- SMA counting start (Advances: 9 months after disbursement, Loans/EMI: 1 month) and the CC/OD stock
|
||||
statement validity window that feeds the NPA trigger. -->
|
||||
<changeSet author="cbsnexora" id="0598_add_loan_product_sma_start_fields">
|
||||
<addColumn tableName="m_product_loan_advance_ext">
|
||||
<column name="sma_start_after_months" type="INT"/>
|
||||
<column name="stock_statement_validity_days" type="INT"/>
|
||||
<column name="elig_member_required" type="BOOLEAN"/>
|
||||
<column name="elig_guarantor_must_be_member" type="BOOLEAN"/>
|
||||
<column name="elig_income_multiple" type="DECIMAL(10,2)"/>
|
||||
<column name="elig_min_vintage_months" type="INT"/>
|
||||
<column name="required_documents" type="VARCHAR(1000)"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!-- RBI 2026 ECL framework: a delinquency range only ever decided an SMA/NPA label by day-count; it now also
|
||||
records which ECL stage (1, 2 or 3) that label maps to, so a product's bucket can drive staging directly
|
||||
instead of a parallel lookup. Nullable: existing ranges keep working as plain labels until re-classified. -->
|
||||
<changeSet author="cbsnexora" id="0599_add_delinquency_range_stage">
|
||||
<addColumn tableName="m_delinquency_range">
|
||||
<column name="stage" type="INT" defaultValueComputed="NULL"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!--
|
||||
Maker-checker on editing a loan or advance product.
|
||||
|
||||
Creating a product already goes to a checker (CREATE_LOANPRODUCT is gated). An edit changes rates,
|
||||
limits, margin, GL accounts and lien rules that live accounts depend on, so it must not take effect on
|
||||
one person's click either. UPDATE_LOANPRODUCT is gated with can_maker_checker = true: an edit lands in
|
||||
m_portfolio_command_source as PENDING and is applied when a checker approves it. UPDATE_LOANPRODUCT_CHECKER
|
||||
already exists and is what approving requires. Roles are left as they are.
|
||||
-->
|
||||
|
||||
<changeSet id="0599_loan_product_update_maker_checker" author="cbsnexora" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
UPDATE m_permission
|
||||
SET can_maker_checker = TRUE
|
||||
WHERE code = 'UPDATE_LOANPRODUCT';
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!-- RBI 2026 ECL framework (Directions para 82): the stage-wise prudential floor, keyed by loan product
|
||||
category rather than by loan product. Seeded below with a representative set of categories; the
|
||||
remaining categories and the category-specific Stage 3 table variants (unsecured retail, housing/other
|
||||
real estate, government-guaranteed) are a follow-up seed, not a schema change. created_by/
|
||||
last_modified_by use 1 (the system user) since this is regulatory data, not something a maker entered. -->
|
||||
<changeSet author="cbsnexora" id="0600_create_prudential_floor_master_table">
|
||||
<createTable tableName="m_prudential_floor">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="product_category" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="stage" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="duration_from_days" type="INT" defaultValueComputed="NULL"/>
|
||||
<column name="duration_to_days" type="INT" defaultValueComputed="NULL"/>
|
||||
<column name="secured_floor_pct" type="DECIMAL(19,6)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="unsecured_floor_pct" type="DECIMAL(19,6)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created_on_utc" type="DATETIME">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="DATETIME">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<createIndex indexName="IX_m_prudential_floor_category_stage" tableName="m_prudential_floor">
|
||||
<column name="product_category"/>
|
||||
<column name="stage"/>
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="cbsnexora" id="0600_add_prudential_floor_permission">
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="READ_PRUDENTIAL_FLOOR"/>
|
||||
<column name="entity_name" value="PRUDENTIAL_FLOOR"/>
|
||||
<column name="action_name" value="READ"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="cbsnexora" id="0600_seed_prudential_floor_stage_1_2">
|
||||
<!-- Stage 1 / Stage 2: a single floor per category (not split secured/unsecured in the Directions),
|
||||
so secured_floor_pct = unsecured_floor_pct here. -->
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Secured Retail Loans"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.40"/><column name="unsecured_floor_pct" valueNumeric="0.40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Secured Retail Loans"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="5.00"/><column name="unsecured_floor_pct" valueNumeric="5.00"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Corporate Loan"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.40"/><column name="unsecured_floor_pct" valueNumeric="0.40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Corporate Loan"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="5.00"/><column name="unsecured_floor_pct" valueNumeric="5.00"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Small and Micro Enterprises"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.25"/><column name="unsecured_floor_pct" valueNumeric="0.25"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Small and Micro Enterprises"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="5.00"/><column name="unsecured_floor_pct" valueNumeric="5.00"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Medium Enterprises"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.40"/><column name="unsecured_floor_pct" valueNumeric="0.40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Medium Enterprises"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="5.00"/><column name="unsecured_floor_pct" valueNumeric="5.00"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Farm Credit - Agricultural Activities"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.25"/><column name="unsecured_floor_pct" valueNumeric="0.25"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Farm Credit - Agricultural Activities"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="5.00"/><column name="unsecured_floor_pct" valueNumeric="5.00"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Unsecured Retail Loans"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="1.00"/><column name="unsecured_floor_pct" valueNumeric="1.00"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Unsecured Retail Loans"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="5.00"/><column name="unsecured_floor_pct" valueNumeric="5.00"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Gold Loan"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.40"/><column name="unsecured_floor_pct" valueNumeric="0.40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Gold Loan"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="1.50"/><column name="unsecured_floor_pct" valueNumeric="1.50"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Housing Loan - Individual"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.25"/><column name="unsecured_floor_pct" valueNumeric="0.25"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Housing Loan - Individual"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="1.50"/><column name="unsecured_floor_pct" valueNumeric="1.50"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Loan against Term Deposit / LIC / KVP"/><column name="stage" valueNumeric="1"/><column name="secured_floor_pct" valueNumeric="0.40"/><column name="unsecured_floor_pct" valueNumeric="0.40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Loan against Term Deposit / LIC / KVP"/><column name="stage" valueNumeric="2"/><column name="secured_floor_pct" valueNumeric="0.40"/><column name="unsecured_floor_pct" valueNumeric="0.40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="cbsnexora" id="0600_seed_prudential_floor_stage_3_standard">
|
||||
<!-- Stage 3 ("standard" duration table, para 82(5) first table): applied here to every seeded category
|
||||
alike as a starting point. The Directions in fact vary this table by category group (housing/real
|
||||
estate and unsecured retail use their own bands) - narrowing this per category is a follow-up seed,
|
||||
not a schema change, since duration_from_days/duration_to_days already carry whatever band a row
|
||||
needs. -->
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Secured Retail Loans"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="25"/><column name="unsecured_floor_pct" valueNumeric="40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Secured Retail Loans"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="duration_to_days" valueNumeric="730"/><column name="secured_floor_pct" valueNumeric="40"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Secured Retail Loans"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="731"/><column name="duration_to_days" valueNumeric="1095"/><column name="secured_floor_pct" valueNumeric="55"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Secured Retail Loans"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1096"/><column name="duration_to_days" valueNumeric="1460"/><column name="secured_floor_pct" valueNumeric="75"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Secured Retail Loans"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1461"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Corporate Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="25"/><column name="unsecured_floor_pct" valueNumeric="40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Corporate Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="duration_to_days" valueNumeric="730"/><column name="secured_floor_pct" valueNumeric="40"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Corporate Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="731"/><column name="duration_to_days" valueNumeric="1095"/><column name="secured_floor_pct" valueNumeric="55"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Corporate Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1096"/><column name="duration_to_days" valueNumeric="1460"/><column name="secured_floor_pct" valueNumeric="75"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Corporate Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1461"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Small and Micro Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="25"/><column name="unsecured_floor_pct" valueNumeric="40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Small and Micro Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="duration_to_days" valueNumeric="730"/><column name="secured_floor_pct" valueNumeric="40"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Small and Micro Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="731"/><column name="duration_to_days" valueNumeric="1095"/><column name="secured_floor_pct" valueNumeric="55"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Small and Micro Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1096"/><column name="duration_to_days" valueNumeric="1460"/><column name="secured_floor_pct" valueNumeric="75"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Small and Micro Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1461"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Medium Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="25"/><column name="unsecured_floor_pct" valueNumeric="40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Medium Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="duration_to_days" valueNumeric="730"/><column name="secured_floor_pct" valueNumeric="40"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Medium Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="731"/><column name="duration_to_days" valueNumeric="1095"/><column name="secured_floor_pct" valueNumeric="55"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Medium Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1096"/><column name="duration_to_days" valueNumeric="1460"/><column name="secured_floor_pct" valueNumeric="75"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Medium Enterprises"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1461"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Farm Credit - Agricultural Activities"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="25"/><column name="unsecured_floor_pct" valueNumeric="40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Farm Credit - Agricultural Activities"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="duration_to_days" valueNumeric="730"/><column name="secured_floor_pct" valueNumeric="40"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Farm Credit - Agricultural Activities"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="731"/><column name="duration_to_days" valueNumeric="1095"/><column name="secured_floor_pct" valueNumeric="55"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Farm Credit - Agricultural Activities"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1096"/><column name="duration_to_days" valueNumeric="1460"/><column name="secured_floor_pct" valueNumeric="75"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Farm Credit - Agricultural Activities"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1461"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Gold Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="25"/><column name="unsecured_floor_pct" valueNumeric="40"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Gold Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="duration_to_days" valueNumeric="730"/><column name="secured_floor_pct" valueNumeric="40"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Gold Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="731"/><column name="duration_to_days" valueNumeric="1095"/><column name="secured_floor_pct" valueNumeric="55"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Gold Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1096"/><column name="duration_to_days" valueNumeric="1460"/><column name="secured_floor_pct" valueNumeric="75"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Gold Loan"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1461"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Housing Loan - Individual"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="10"/><column name="unsecured_floor_pct" valueNumeric="25"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Housing Loan - Individual"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="duration_to_days" valueNumeric="730"/><column name="secured_floor_pct" valueNumeric="20"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Housing Loan - Individual"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="731"/><column name="duration_to_days" valueNumeric="1095"/><column name="secured_floor_pct" valueNumeric="30"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Housing Loan - Individual"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1096"/><column name="duration_to_days" valueNumeric="1460"/><column name="secured_floor_pct" valueNumeric="40"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Housing Loan - Individual"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="1461"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Unsecured Retail Loans"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="duration_to_days" valueNumeric="365"/><column name="secured_floor_pct" valueNumeric="25"/><column name="unsecured_floor_pct" valueNumeric="25"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Unsecured Retail Loans"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="366"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
|
||||
<insert tableName="m_prudential_floor"><column name="product_category" value="Loan against Term Deposit / LIC / KVP"/><column name="stage" valueNumeric="3"/><column name="duration_from_days" valueNumeric="0"/><column name="secured_floor_pct" valueNumeric="100"/><column name="unsecured_floor_pct" valueNumeric="100"/><column name="created_by" valueNumeric="1"/><column name="created_on_utc" valueComputed="NOW()"/><column name="version" valueNumeric="1"/><column name="last_modified_by" valueNumeric="1"/><column name="last_modified_on_utc" valueComputed="NOW()"/></insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!-- RBI 2026 ECL framework, Penal/SMA/NPA wizard step: SICR trigger configuration and the LGD backstop /
|
||||
own-model override. The prudential floor % itself is NOT stored here - it is looked up from
|
||||
m_prudential_floor by product category, so every product stays in sync with a single regulatory table. -->
|
||||
<changeSet author="cbsnexora" id="0601_add_loan_product_advance_ext_sicr_lgd_fields">
|
||||
<addColumn tableName="m_product_loan_advance_ext">
|
||||
<!-- SICR trigger configuration -->
|
||||
<column name="sicr_days_threshold" type="INT"/>
|
||||
<column name="sicr_revolving_days_threshold" type="INT"/>
|
||||
<column name="sicr_rating_downgrade_notches" type="INT"/>
|
||||
<column name="sicr_pricing_increase_trigger_pct" type="DECIMAL(19,6)"/>
|
||||
<column name="sicr_assessment_basis" type="VARCHAR(30)"/>
|
||||
<column name="sicr_rebuttal_allowed" type="BOOLEAN"/>
|
||||
<!-- NPA trigger extras -->
|
||||
<column name="npa_out_of_order_basis" type="VARCHAR(60)"/>
|
||||
<column name="crop_duration" type="VARCHAR(20)"/>
|
||||
<!-- LGD backstop / override -->
|
||||
<column name="use_own_lgd_model" type="BOOLEAN"/>
|
||||
<column name="lgd_secured_pct" type="DECIMAL(19,6)"/>
|
||||
<column name="lgd_unsecured_pct" type="DECIMAL(19,6)"/>
|
||||
<column name="eligible_collateral_type" type="VARCHAR(200)"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+2
-2
@@ -173,7 +173,7 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
|
||||
when(loanAccountData.getId()).thenReturn(1L);
|
||||
when(loanAccountData.getAccountNo()).thenReturn("0001");
|
||||
when(loanAccountData.getExternalId()).thenReturn(ExternalIdFactory.produce("externalId"));
|
||||
when(loanAccountData.getDelinquencyRange()).thenReturn(new DelinquencyRangeData(1L, "classification", 1, 10));
|
||||
when(loanAccountData.getDelinquencyRange()).thenReturn(new DelinquencyRangeData(1L, "classification", 1, 10, null));
|
||||
when(loanAccountData.getCurrency()).thenAnswer(
|
||||
a -> new CurrencyData(loanCurrency.getCode(), loanCurrency.getDigitsAfterDecimal(), loanCurrency.getInMultiplesOf()));
|
||||
when(loanForProcessing.getCurrency()).thenReturn(loanCurrency);
|
||||
@@ -238,7 +238,7 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
|
||||
when(loanAccountData.getId()).thenReturn(1L);
|
||||
when(loanAccountData.getAccountNo()).thenReturn("0001");
|
||||
when(loanAccountData.getExternalId()).thenReturn(ExternalIdFactory.produce("externalId"));
|
||||
when(loanAccountData.getDelinquencyRange()).thenReturn(new DelinquencyRangeData(1L, "classification", 1, 10));
|
||||
when(loanAccountData.getDelinquencyRange()).thenReturn(new DelinquencyRangeData(1L, "classification", 1, 10, null));
|
||||
when(loanAccountData.getCurrency()).thenAnswer(
|
||||
a -> new CurrencyData(loanCurrency.getCode(), loanCurrency.getDigitsAfterDecimal(), loanCurrency.getInMultiplesOf()));
|
||||
when(loanForProcessing.getCurrency()).thenReturn(loanCurrency);
|
||||
|
||||
+14
-14
@@ -174,9 +174,9 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
||||
final List<LoanDelinquencyActionData> effectiveDelinquencyList = Collections.emptyList();
|
||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2, null);
|
||||
range1.setId(1L);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30, null);
|
||||
range2.setId(2L);
|
||||
List<DelinquencyRange> listDelinquencyRanges = Arrays.asList(range1, range2);
|
||||
DelinquencyBucket delinquencyBucket = new DelinquencyBucket("test Bucket");
|
||||
@@ -217,9 +217,9 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
||||
final List<LoanDelinquencyActionData> effectiveDelinquencyList = Collections.emptyList();
|
||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2, null);
|
||||
range1.setId(1L);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30, null);
|
||||
range2.setId(2L);
|
||||
List<DelinquencyRange> listDelinquencyRanges = Arrays.asList(range1, range2);
|
||||
DelinquencyBucket delinquencyBucket = new DelinquencyBucket("test Bucket");
|
||||
@@ -281,9 +281,9 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
||||
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2, null);
|
||||
range1.setId(1L);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30, null);
|
||||
range2.setId(2L);
|
||||
List<DelinquencyRange> listDelinquencyRanges = Arrays.asList(range1, range2);
|
||||
|
||||
@@ -346,9 +346,9 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
||||
final List<LoanDelinquencyActionData> effectiveDelinquencyList = Collections.emptyList();
|
||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2, null);
|
||||
range1.setId(1L);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30, null);
|
||||
range2.setId(2L);
|
||||
List<DelinquencyRange> listDelinquencyRanges = Arrays.asList(range1, range2);
|
||||
DelinquencyBucket delinquencyBucket = new DelinquencyBucket("test Bucket");
|
||||
@@ -425,9 +425,9 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
||||
final List<LoanDelinquencyActionData> effectiveDelinquencyList = Collections.emptyList();
|
||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2, null);
|
||||
range1.setId(1L);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30, null);
|
||||
range2.setId(2L);
|
||||
List<DelinquencyRange> listDelinquencyRanges = Arrays.asList(range1, range2);
|
||||
DelinquencyBucket delinquencyBucket = new DelinquencyBucket("test Bucket");
|
||||
@@ -510,9 +510,9 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
||||
// given
|
||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2, null);
|
||||
range1.setId(1L);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30, null);
|
||||
range2.setId(2L);
|
||||
List<DelinquencyRange> listDelinquencyRanges = Arrays.asList(range1, range2);
|
||||
DelinquencyBucket delinquencyBucket = new DelinquencyBucket("test Bucket");
|
||||
@@ -597,9 +597,9 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
||||
// given
|
||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||
when(loanForProcessing.getId()).thenReturn(1L);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2);
|
||||
DelinquencyRange range1 = DelinquencyRange.instance("Range1", 1, 2, null);
|
||||
range1.setId(1L);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30);
|
||||
DelinquencyRange range2 = DelinquencyRange.instance("Range30", 3, 30, null);
|
||||
range2.setId(2L);
|
||||
List<DelinquencyRange> listDelinquencyRanges = Arrays.asList(range1, range2);
|
||||
DelinquencyBucket delinquencyBucket = new DelinquencyBucket("test Bucket");
|
||||
|
||||
Reference in New Issue
Block a user