implementation of loan product creation
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
This commit is contained in:
+20
@@ -1466,6 +1466,26 @@ public class LoanProductData implements Serializable {
|
||||
this.allowAttributeOverrides = loanProductConfigurableAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* The legacy "Account Type Creation" fields, flat and keyed by their form field name.
|
||||
*
|
||||
* Set after construction rather than through a constructor parameter: the main constructor already
|
||||
* takes over a hundred arguments, and threading two more through it would touch every call site for
|
||||
* no benefit. Follows the same pattern as setLoanProductConfigurableAttributes above.
|
||||
*/
|
||||
private Map<String, Object> cbsExtensions;
|
||||
|
||||
/** The legacy Interest Rate Detail grid: one entry per interest type, in form order. */
|
||||
private List<Map<String, Object>> interestRateDetail;
|
||||
|
||||
public void setCbsExtensions(final Map<String, Object> cbsExtensions) {
|
||||
this.cbsExtensions = cbsExtensions;
|
||||
}
|
||||
|
||||
public void setInterestRateDetail(final List<Map<String, Object>> interestRateDetail) {
|
||||
this.interestRateDetail = interestRateDetail;
|
||||
}
|
||||
|
||||
public boolean isIsLinkedToFloatingInterestRates() {
|
||||
return this.isLinkedToFloatingInterestRates;
|
||||
}
|
||||
|
||||
+740
@@ -0,0 +1,740 @@
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanproduct.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The legacy "Account Type Creation" configuration for a loan product.
|
||||
*
|
||||
* Fineract's loan product schema has no home for these fields, and they are specific to this
|
||||
* deployment, so they hang off {@link LoanProduct} 1:1 instead of widening m_product_loan - an
|
||||
* upstream change to that table can then never collide with them.
|
||||
*
|
||||
* Loan account creation reads this at origination time, which is why these are typed columns rather
|
||||
* than a JSON blob: callers get a compile-checked getter and reports get a plain column.
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Table(name = "m_product_loan_cbs_ext")
|
||||
public class LoanProductCbsExt {
|
||||
|
||||
@Id
|
||||
@Column(name = "loan_product_id")
|
||||
private Long loanProductId;
|
||||
|
||||
/**
|
||||
* Shared primary key: this and {@link #loanProductId} are the same column, so the association is
|
||||
* mapped read-only and {@code loanProductId} is the one that writes it. EclipseLink rejects an
|
||||
* entity with two writable mappings for one field.
|
||||
*/
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "loan_product_id", insertable = false, updatable = false)
|
||||
private LoanProduct loanProduct;
|
||||
|
||||
// ---- classification & legacy header fields (24) ---------------------
|
||||
|
||||
@Column(name = "product_type_group")
|
||||
private String productTypeGroup;
|
||||
|
||||
@Column(name = "product_type_sub_group")
|
||||
private String productTypeSubGroup;
|
||||
|
||||
@Column(name = "debit_int_calculation")
|
||||
private Boolean debitIntCalculation;
|
||||
|
||||
@Column(name = "separate_penal_interest")
|
||||
private Boolean separatePenalInterest;
|
||||
|
||||
@Column(name = "credit_int_calculation")
|
||||
private Boolean creditIntCalculation;
|
||||
|
||||
@Column(name = "sub_account_type_balance")
|
||||
private Boolean subAccountTypeBalance;
|
||||
|
||||
@Column(name = "final_int_rounding")
|
||||
private Boolean finalIntRounding;
|
||||
|
||||
@Column(name = "rounding_up_to")
|
||||
private Integer roundingUpTo;
|
||||
|
||||
@Column(name = "account_type_code")
|
||||
private String accountTypeCode;
|
||||
|
||||
@Column(name = "micr_transaction_code")
|
||||
private String micrTransactionCode;
|
||||
|
||||
@Column(name = "reserved_ecs_serial_number")
|
||||
private String reservedEcsSerialNumber;
|
||||
|
||||
@Column(name = "reverse_ecs_number")
|
||||
private String reverseEcsNumber;
|
||||
|
||||
@Column(name = "lock_cheque_info_enabled")
|
||||
private Boolean lockChequeInfoEnabled;
|
||||
|
||||
@Column(name = "lock_page_two_info_enabled")
|
||||
private Boolean lockPageTwoInfoEnabled;
|
||||
|
||||
@Column(name = "computerization_date")
|
||||
private LocalDate computerizationDate;
|
||||
|
||||
@Column(name = "cheque_print_description")
|
||||
private String chequePrintDescription;
|
||||
|
||||
@Column(name = "pos_account_type_description")
|
||||
private String posAccountTypeDescription;
|
||||
|
||||
@Column(name = "pfms_account_type")
|
||||
private String pfmsAccountType;
|
||||
|
||||
@Column(name = "renewal_date_add_months")
|
||||
private Integer renewalDateAddMonths;
|
||||
|
||||
@Column(name = "document_renewal_date_add_months")
|
||||
private Integer documentRenewalDateAddMonths;
|
||||
|
||||
@Column(name = "pps_limit")
|
||||
private BigDecimal ppsLimit;
|
||||
|
||||
@Column(name = "is_write_off_account_type")
|
||||
private Boolean isWriteOffAccountType;
|
||||
|
||||
@Column(name = "write_off_account_type_code")
|
||||
private String writeOffAccountTypeCode;
|
||||
|
||||
@Column(name = "renewal_grace_days")
|
||||
private Integer renewalGraceDays;
|
||||
|
||||
// ---- Cheque Book Settings (10) --------------------------------------
|
||||
|
||||
@Column(name = "cheque_book_issue_enabled")
|
||||
private Boolean chequeBookIssueEnabled;
|
||||
|
||||
@Column(name = "cheque_validation_required")
|
||||
private Boolean chequeValidationRequired;
|
||||
|
||||
@Column(name = "is_first_cheque_book_free")
|
||||
private Boolean isFirstChequeBookFree;
|
||||
|
||||
@Column(name = "cheque_printing_account_type")
|
||||
private String chequePrintingAccountType;
|
||||
|
||||
@Column(name = "allow_withdrawal_slip_usage")
|
||||
private Boolean allowWithdrawalSlipUsage;
|
||||
|
||||
@Column(name = "maintain_cheque_book_stock_registry")
|
||||
private Boolean maintainChequeBookStockRegistry;
|
||||
|
||||
@Column(name = "free_cheque_books_per_year")
|
||||
private Integer freeChequeBooksPerYear;
|
||||
|
||||
@Column(name = "allow_credit_by_cheque_number")
|
||||
private Boolean allowCreditByChequeNumber;
|
||||
|
||||
@Column(name = "credit_cheque_validation_required")
|
||||
private Boolean creditChequeValidationRequired;
|
||||
|
||||
@Column(name = "grace_days_for_stock_statement")
|
||||
private Integer graceDaysForStockStatement;
|
||||
|
||||
// ---- Additional Product Settings (37) -------------------------------
|
||||
|
||||
@Column(name = "account_type_active_for_transactions")
|
||||
private Boolean accountTypeActiveForTransactions;
|
||||
|
||||
@Column(name = "sub_type_activity_enabled")
|
||||
private Boolean subTypeActivityEnabled;
|
||||
|
||||
@Column(name = "account_opening_charges")
|
||||
private BigDecimal accountOpeningCharges;
|
||||
|
||||
@Column(name = "maximum_gold_loan_limit")
|
||||
private BigDecimal maximumGoldLoanLimit;
|
||||
|
||||
@Column(name = "last_account_number_opened")
|
||||
private String lastAccountNumberOpened;
|
||||
|
||||
@Column(name = "customer_termination_allowed")
|
||||
private Boolean customerTerminationAllowed;
|
||||
|
||||
@Column(name = "charges_for_cash_credit_above_limit")
|
||||
private BigDecimal chargesForCashCreditAboveLimit;
|
||||
|
||||
@Column(name = "death_interest_gl_account")
|
||||
private String deathInterestGLAccount;
|
||||
|
||||
@Column(name = "starting_ledger_number")
|
||||
private Integer startingLedgerNumber;
|
||||
|
||||
@Column(name = "ending_ledger_number")
|
||||
private Integer endingLedgerNumber;
|
||||
|
||||
@Column(name = "current_ledger_number")
|
||||
private Integer currentLedgerNumber;
|
||||
|
||||
@Column(name = "remittance_account_number")
|
||||
private String remittanceAccountNumber;
|
||||
|
||||
@Column(name = "is_non_resident_indian_account")
|
||||
private Boolean isNonResidentIndianAccount;
|
||||
|
||||
@Column(name = "debit_clearing_gl_account")
|
||||
private String debitClearingGLAccount;
|
||||
|
||||
@Column(name = "missed_call_alert_service_active")
|
||||
private Boolean missedCallAlertServiceActive;
|
||||
|
||||
@Column(name = "standing_instruction_charge_gl_account")
|
||||
private String standingInstructionChargeGLAccount;
|
||||
|
||||
@Column(name = "standing_instruction_debit_charge_skip_option")
|
||||
private String standingInstructionDebitChargeSkipOption;
|
||||
|
||||
@Column(name = "opening_balance_multiplier_for_remittance_charges")
|
||||
private BigDecimal openingBalanceMultiplierForRemittanceCharges;
|
||||
|
||||
@Column(name = "gold_loan_packet_number_with_year_enabled")
|
||||
private Boolean goldLoanPacketNumberWithYearEnabled;
|
||||
|
||||
@Column(name = "account_move_to_inoperative_enabled")
|
||||
private Boolean accountMoveToInoperativeEnabled;
|
||||
|
||||
@Column(name = "generate_gl_diff_entry_enabled")
|
||||
private Boolean generateGlDiffEntryEnabled;
|
||||
|
||||
@Column(name = "sub_type_wise_gl_balance_generation_enabled")
|
||||
private Boolean subTypeWiseGlBalanceGenerationEnabled;
|
||||
|
||||
@Column(name = "validate_before_deleting_debit_entry_enabled")
|
||||
private Boolean validateBeforeDeletingDebitEntryEnabled;
|
||||
|
||||
@Column(name = "rc_file_concept_enabled")
|
||||
private Boolean rcFileConceptEnabled;
|
||||
|
||||
@Column(name = "account_close_zero_balance_in_open_day_process")
|
||||
private Boolean accountCloseZeroBalanceInOpenDayProcess;
|
||||
|
||||
@Column(name = "account_close_zero_balance_at_subledger_tran_entry")
|
||||
private Boolean accountCloseZeroBalanceAtSubledgerTranEntry;
|
||||
|
||||
@Column(name = "limit_enhancement_against_clearing_screen_display_enabled")
|
||||
private Boolean limitEnhancementAgainstClearingScreenDisplayEnabled;
|
||||
|
||||
@Column(name = "advance_interest_parameter_in_ledger_enabled")
|
||||
private Boolean advanceInterestParameterInLedgerEnabled;
|
||||
|
||||
@Column(name = "vehicle_detail_in_master_enabled")
|
||||
private Boolean vehicleDetailInMasterEnabled;
|
||||
|
||||
@Column(name = "deleted_cheque_issue_enabled")
|
||||
private Boolean deletedChequeIssueEnabled;
|
||||
|
||||
@Column(name = "dp_reduce_in_document_renewal_date_enabled")
|
||||
private Boolean dpReduceInDocumentRenewalDateEnabled;
|
||||
|
||||
@Column(name = "dp_reduce_in_renewal_date_enabled")
|
||||
private Boolean dpReduceInRenewalDateEnabled;
|
||||
|
||||
@Column(name = "auto_close_at_day_end_enabled")
|
||||
private Boolean autoCloseAtDayEndEnabled;
|
||||
|
||||
@Column(name = "loan_rate_from_master_enabled")
|
||||
private Boolean loanRateFromMasterEnabled;
|
||||
|
||||
@Column(name = "cheque_short_name")
|
||||
private String chequeShortName;
|
||||
|
||||
@Column(name = "statement_print_enabled")
|
||||
private Boolean statementPrintEnabled;
|
||||
|
||||
@Column(name = "nesl_code")
|
||||
private String neslCode;
|
||||
|
||||
// ---- Interest Related Parameters (53) -------------------------------
|
||||
|
||||
@Column(name = "drawing_power_and_limit_generation_procedure")
|
||||
private String drawingPowerAndLimitGenerationProcedure;
|
||||
|
||||
@Column(name = "advances_interest_calculation_method")
|
||||
private String advancesInterestCalculationMethod;
|
||||
|
||||
@Column(name = "against_interest_calculation_enabled")
|
||||
private Boolean againstInterestCalculationEnabled;
|
||||
|
||||
@Column(name = "day_wise_against_clearing_interest_rounding")
|
||||
private Boolean dayWiseAgainstClearingInterestRounding;
|
||||
|
||||
@Column(name = "interest_calculation_one_fourth_method")
|
||||
private String interestCalculationOneFourthMethod;
|
||||
|
||||
@Column(name = "against_clearing_interest_procedure_type")
|
||||
private String againstClearingInterestProcedureType;
|
||||
|
||||
@Column(name = "consider_debit_closing_amount_for_against_clearing")
|
||||
private Boolean considerDebitClosingAmountForAgainstClearing;
|
||||
|
||||
@Column(name = "interest_rounding_method")
|
||||
private String interestRoundingMethod;
|
||||
|
||||
@Column(name = "penalty_interest_calculation_enabled")
|
||||
private Boolean penaltyInterestCalculationEnabled;
|
||||
|
||||
@Column(name = "penalty_interest_calculation_method")
|
||||
private String penaltyInterestCalculationMethod;
|
||||
|
||||
@Column(name = "penalty_interest_procedure_number")
|
||||
private String penaltyInterestProcedureNumber;
|
||||
|
||||
@Column(name = "overdrawn_interest_calculation_method")
|
||||
private String overdrawnInterestCalculationMethod;
|
||||
|
||||
@Column(name = "calculate_overdrawn_interest_after_renewal")
|
||||
private Boolean calculateOverdrawnInterestAfterRenewal;
|
||||
|
||||
@Column(name = "interest_on_credit_balance")
|
||||
private Boolean interestOnCreditBalance;
|
||||
|
||||
@Column(name = "penalty_interest_date_different_than_regular_interest")
|
||||
private Boolean penaltyInterestDateDifferentThanRegularInterest;
|
||||
|
||||
@Column(name = "fixed_deposit_overdraft_certificate_sort_order")
|
||||
private String fixedDepositOverdraftCertificateSortOrder;
|
||||
|
||||
@Column(name = "use_document_submission_date_for_interest")
|
||||
private Boolean useDocumentSubmissionDateForInterest;
|
||||
|
||||
@Column(name = "loan_management_system_renewal_penalty_active")
|
||||
private Boolean loanManagementSystemRenewalPenaltyActive;
|
||||
|
||||
@Column(name = "minimum_normal_interest_amount")
|
||||
private BigDecimal minimumNormalInterestAmount;
|
||||
|
||||
@Column(name = "minimum_interest_calculation_method")
|
||||
private String minimumInterestCalculationMethod;
|
||||
|
||||
@Column(name = "minimum_against_clearing_interest_amount")
|
||||
private BigDecimal minimumAgainstClearingInterestAmount;
|
||||
|
||||
@Column(name = "limit_increase_upto_interest_amount_in_interest_calculation")
|
||||
private Boolean limitIncreaseUptoInterestAmountInInterestCalculation;
|
||||
|
||||
@Column(name = "minimum_penalty_interest_amount")
|
||||
private BigDecimal minimumPenaltyInterestAmount;
|
||||
|
||||
@Column(name = "days_for_limit_increase_upto_interest_amount")
|
||||
private Integer daysForLimitIncreaseUptoInterestAmount;
|
||||
|
||||
@Column(name = "additional_interest_rate_for_fixed_deposit_overdraft")
|
||||
private BigDecimal additionalInterestRateForFixedDepositOverdraft;
|
||||
|
||||
@Column(name = "consider_dd_payorder_in_against_clearing_interest_calculation")
|
||||
private Boolean considerDdPayorderInAgainstClearingInterestCalculation;
|
||||
|
||||
@Column(name = "grace_days_after_renew_date")
|
||||
private Integer graceDaysAfterRenewDate;
|
||||
|
||||
@Column(name = "apply_undebited_interest_concept_enabled")
|
||||
private Boolean applyUndebitedInterestConceptEnabled;
|
||||
|
||||
@Column(name = "interest_register_print_format_type")
|
||||
private String interestRegisterPrintFormatType;
|
||||
|
||||
@Column(name = "normal_grace_days_after_overdue")
|
||||
private Integer normalGraceDaysAfterOverdue;
|
||||
|
||||
@Column(name = "allow_against_clearing_entry")
|
||||
private Boolean allowAgainstClearingEntry;
|
||||
|
||||
@Column(name = "allow_no_balance_entry")
|
||||
private Boolean allowNoBalanceEntry;
|
||||
|
||||
@Column(name = "fd_od_penalty_interest_combined_with_normal_interest")
|
||||
private Boolean fixedDepositOverdraftPenaltyInterestCombinedWithNormalInterest;
|
||||
|
||||
@Column(name = "allow_no_balance_entry_with_password")
|
||||
private Boolean allowNoBalanceEntryWithPassword;
|
||||
|
||||
@Column(name = "undebited_simple_interest_account_wise")
|
||||
private Boolean undebitedSimpleInterestAccountWise;
|
||||
|
||||
@Column(name = "daily_interest_calculation_enabled")
|
||||
private Boolean dailyInterestCalculationEnabled;
|
||||
|
||||
@Column(name = "daily_interest_calculation_start_date")
|
||||
private String dailyInterestCalculationStartDate;
|
||||
|
||||
@Column(name = "non_performing_asset_penal_interest_rate_update")
|
||||
private Boolean nonPerformingAssetPenalInterestRateUpdate;
|
||||
|
||||
@Column(name = "non_performing_asset_penal_interest_rate")
|
||||
private BigDecimal nonPerformingAssetPenalInterestRate;
|
||||
|
||||
@Column(name = "fd_od_penal_interest_rate_update_in_branch_process")
|
||||
private Boolean fixedDepositOverdraftPenalInterestRateUpdateInBranchProcess;
|
||||
|
||||
@Column(name = "add_penal_interest_rate")
|
||||
private BigDecimal addPenalInterestRate;
|
||||
|
||||
@Column(name = "atyp14_simple_interest_enabled")
|
||||
private Boolean atyp14SimpleInterestEnabled;
|
||||
|
||||
@Column(name = "fixed_deposit_overdraft_margin_type")
|
||||
private String fixedDepositOverdraftMarginType;
|
||||
|
||||
@Column(name = "check_master_detail_edited_passing_pending_enabled")
|
||||
private Boolean checkMasterDetailEditedPassingPendingEnabled;
|
||||
|
||||
@Column(name = "credit_debit_interest_calculation_separate_enabled")
|
||||
private Boolean creditDebitInterestCalculationSeparateEnabled;
|
||||
|
||||
@Column(name = "on_time_interest_provision_enabled")
|
||||
private Boolean onTimeInterestProvisionEnabled;
|
||||
|
||||
@Column(name = "check_against_clearing_enabled")
|
||||
private Boolean checkAgainstClearingEnabled;
|
||||
|
||||
@Column(name = "gst_on_penalty_enabled")
|
||||
private Boolean gstOnPenaltyEnabled;
|
||||
|
||||
@Column(name = "penalty_interest_grace_days")
|
||||
private Integer penaltyInterestGraceDays;
|
||||
|
||||
@Column(name = "overdrawn_interest_rate")
|
||||
private BigDecimal overdrawnInterestRate;
|
||||
|
||||
@Column(name = "calculate_daily_limit_enhancement_tod_enabled")
|
||||
private Boolean calculateDailyLimitEnhancementTodEnabled;
|
||||
|
||||
@Column(name = "fixed_deposit_overdraft_multiple_interest_rate_enabled")
|
||||
private Boolean fixedDepositOverdraftMultipleInterestRateEnabled;
|
||||
|
||||
@Column(name = "grace_days_after_overdue_for_moratorium")
|
||||
private Integer graceDaysAfterOverdueForMoratorium;
|
||||
|
||||
// ---- Credit Bureau Settings (CIBIL) (8) ----------------------------
|
||||
|
||||
@Column(name = "cibil_account_type")
|
||||
private String cibilAccountType;
|
||||
|
||||
@Column(name = "cibil_commercial_account_type")
|
||||
private String cibilCommercialAccountType;
|
||||
|
||||
@Column(name = "highmark_account_type")
|
||||
private String highmarkAccountType;
|
||||
|
||||
@Column(name = "highmark_commercial_account_type")
|
||||
private String highmarkCommercialAccountType;
|
||||
|
||||
@Column(name = "experian_account_type")
|
||||
private String experianAccountType;
|
||||
|
||||
@Column(name = "experian_commercial_account_type")
|
||||
private String experianCommercialAccountType;
|
||||
|
||||
@Column(name = "equifax_account_type")
|
||||
private String equifaxAccountType;
|
||||
|
||||
@Column(name = "equifax_commercial_account_type")
|
||||
private String equifaxCommercialAccountType;
|
||||
|
||||
// ---- RBI Compliance & Product Category (6) -------------------------
|
||||
|
||||
@Column(name = "loan_product_category")
|
||||
private String loanProductCategory;
|
||||
|
||||
@Column(name = "penal_charge_method")
|
||||
private String penalChargeMethod;
|
||||
|
||||
@Column(name = "is_floating_rate")
|
||||
private Boolean isFloatingRate;
|
||||
|
||||
@Column(name = "foreclosure_charges_applicable")
|
||||
private Boolean foreclosureChargesApplicable;
|
||||
|
||||
@Column(name = "key_fact_statement_enabled")
|
||||
private Boolean keyFactStatementEnabled;
|
||||
|
||||
@Column(name = "annual_percentage_rate_calculation_enabled")
|
||||
private Boolean annualPercentageRateCalculationEnabled;
|
||||
|
||||
// ---- Channel & Transaction Limits (23) ------------------------------
|
||||
|
||||
@Column(name = "is_mobile_app_enabled")
|
||||
private Boolean isMobileAppEnabled;
|
||||
|
||||
@Column(name = "is_atm_enabled")
|
||||
private Boolean isAtmEnabled;
|
||||
|
||||
@Column(name = "atm_yearly_charge_enabled")
|
||||
private Boolean atmYearlyChargeEnabled;
|
||||
|
||||
@Column(name = "atm_minimum_balance")
|
||||
private BigDecimal atmMinimumBalance;
|
||||
|
||||
@Column(name = "email_active_enabled")
|
||||
private Boolean emailActiveEnabled;
|
||||
|
||||
@Column(name = "is_imps_enabled")
|
||||
private Boolean isImpsEnabled;
|
||||
|
||||
@Column(name = "is_upi_enabled")
|
||||
private Boolean isUpiEnabled;
|
||||
|
||||
@Column(name = "is_pos_enabled")
|
||||
private Boolean isPosEnabled;
|
||||
|
||||
@Column(name = "is_bbps_enabled")
|
||||
private Boolean isBbpsEnabled;
|
||||
|
||||
@Column(name = "inter_bank_limit_per_day")
|
||||
private BigDecimal interBankLimitPerDay;
|
||||
|
||||
@Column(name = "inter_bank_limit_per_transaction")
|
||||
private BigDecimal interBankLimitPerTransaction;
|
||||
|
||||
@Column(name = "neft_rtgs_limit_per_day")
|
||||
private BigDecimal neftRtgsLimitPerDay;
|
||||
|
||||
@Column(name = "neft_rtgs_limit_per_transaction")
|
||||
private BigDecimal neftRtgsLimitPerTransaction;
|
||||
|
||||
@Column(name = "neft_cutoff_limit")
|
||||
private BigDecimal neftCutoffLimit;
|
||||
|
||||
@Column(name = "rtgs_cutoff_limit")
|
||||
private BigDecimal rtgsCutoffLimit;
|
||||
|
||||
@Column(name = "neft_rtgs_minimum_balance")
|
||||
private BigDecimal neftRtgsMinimumBalance;
|
||||
|
||||
@Column(name = "is_charge_required_neft_rtgs_cbs")
|
||||
private Boolean isChargeRequiredNeftRtgsCbs;
|
||||
|
||||
@Column(name = "is_charge_required_neft_rtgs_mobile")
|
||||
private Boolean isChargeRequiredNeftRtgsMobile;
|
||||
|
||||
@Column(name = "imps_limit_per_day")
|
||||
private BigDecimal impsLimitPerDay;
|
||||
|
||||
@Column(name = "imps_limit_per_transaction")
|
||||
private BigDecimal impsLimitPerTransaction;
|
||||
|
||||
@Column(name = "imps_limit_per_month")
|
||||
private BigDecimal impsLimitPerMonth;
|
||||
|
||||
@Column(name = "imps_min_limit")
|
||||
private BigDecimal impsMinLimit;
|
||||
|
||||
@Column(name = "imps_monthly_transaction_count")
|
||||
private Integer impsMonthlyTransactionCount;
|
||||
|
||||
// ---- POS Facility & ATM CSV Settings (10) ---------------------------
|
||||
|
||||
@Column(name = "max_per_transaction_limit_atm")
|
||||
private BigDecimal maxPerTransactionLimitAtm;
|
||||
|
||||
@Column(name = "max_day_transaction_limit_atm")
|
||||
private BigDecimal maxDayTransactionLimitAtm;
|
||||
|
||||
@Column(name = "max_per_transaction_limit_pos")
|
||||
private BigDecimal maxPerTransactionLimitPos;
|
||||
|
||||
@Column(name = "max_day_transaction_limit_pos")
|
||||
private BigDecimal maxDayTransactionLimitPos;
|
||||
|
||||
@Column(name = "max_per_transaction_limit_ecom")
|
||||
private BigDecimal maxPerTransactionLimitEcom;
|
||||
|
||||
@Column(name = "max_day_transaction_limit_ecom")
|
||||
private BigDecimal maxDayTransactionLimitEcom;
|
||||
|
||||
@Column(name = "max_per_transaction_limit_upi")
|
||||
private BigDecimal maxPerTransactionLimitUpi;
|
||||
|
||||
@Column(name = "max_day_transaction_limit_upi")
|
||||
private BigDecimal maxDayTransactionLimitUpi;
|
||||
|
||||
@Column(name = "atm_csv_product_code")
|
||||
private String atmCsvProductCode;
|
||||
|
||||
@Column(name = "atm_csv_type_code")
|
||||
private String atmCsvTypeCode;
|
||||
|
||||
// ---- Auto Interest Post Parameters (4) -----------------------------
|
||||
|
||||
@Column(name = "auto_interest_post_type")
|
||||
private String autoInterestPostType;
|
||||
|
||||
@Column(name = "auto_interest_post_when")
|
||||
private String autoInterestPostWhen;
|
||||
|
||||
@Column(name = "auto_interest_post_fix_day")
|
||||
private Integer autoInterestPostFixDay;
|
||||
|
||||
@Column(name = "auto_last_interest_date")
|
||||
private String autoLastInterestDate;
|
||||
|
||||
// ---- Foreclosure / Early Account Closure (3) -----------------------
|
||||
|
||||
@Column(name = "calculate_early_account_close_charge")
|
||||
private Boolean calculateEarlyAccountCloseCharge;
|
||||
|
||||
@Column(name = "early_account_close_charge")
|
||||
private BigDecimal earlyAccountCloseCharge;
|
||||
|
||||
@Column(name = "early_account_close_period_in_months")
|
||||
private Integer earlyAccountClosePeriodInMonths;
|
||||
|
||||
// ---- Terms step (3) ------------------------------------------------
|
||||
|
||||
@Column(name = "debit_balance_allow")
|
||||
private Boolean debitBalanceAllow;
|
||||
|
||||
@Column(name = "allow_debit_trans_after_due_date")
|
||||
private Boolean allowDebitTransAfterDueDate;
|
||||
|
||||
@Column(name = "branch_level_account_type")
|
||||
private Boolean branchLevelAccountType;
|
||||
|
||||
// ---- legacy cheque / standing instruction / minimum balance charges (24)
|
||||
|
||||
@Column(name = "cheque_book_charge_enabled")
|
||||
private Boolean chequeBookChargeEnabled;
|
||||
|
||||
@Column(name = "cheque_return_charge_enabled")
|
||||
private Boolean chequeReturnChargeEnabled;
|
||||
|
||||
@Column(name = "ic_charge_debit_enabled")
|
||||
private Boolean icChargeDebitEnabled;
|
||||
|
||||
@Column(name = "cash_bundle_charge_enabled")
|
||||
private Boolean cashBundleChargeEnabled;
|
||||
|
||||
@Column(name = "cash_bundle_charge_with_pan_limit")
|
||||
private BigDecimal cashBundleChargeWithPanLimit;
|
||||
|
||||
@Column(name = "per_cheque_entry_charge")
|
||||
private BigDecimal perChequeEntryCharge;
|
||||
|
||||
@Column(name = "per_cheque_entry_service_charge")
|
||||
private BigDecimal perChequeEntryServiceCharge;
|
||||
|
||||
@Column(name = "per_inward_cheque_entry_charge")
|
||||
private BigDecimal perInwardChequeEntryCharge;
|
||||
|
||||
@Column(name = "per_outward_cheque_entry_charge")
|
||||
private BigDecimal perOutwardChequeEntryCharge;
|
||||
|
||||
@Column(name = "creditor_standing_instruction_fail_charge")
|
||||
private BigDecimal creditorStandingInstructionFailCharge;
|
||||
|
||||
@Column(name = "debtor_standing_instruction_fail_charge")
|
||||
private BigDecimal debtorStandingInstructionFailCharge;
|
||||
|
||||
@Column(name = "minimum_balance_checking_type")
|
||||
private String minimumBalanceCheckingType;
|
||||
|
||||
@Column(name = "auto_minimum_balance_charge")
|
||||
private Boolean autoMinimumBalanceCharge;
|
||||
|
||||
@Column(name = "calculate_daily_minimum_balance_charges")
|
||||
private Boolean calculateDailyMinimumBalanceCharges;
|
||||
|
||||
@Column(name = "minimum_balance_charge_enabled")
|
||||
private Boolean minimumBalanceChargeEnabled;
|
||||
|
||||
@Column(name = "minimum_balance_charge_amount")
|
||||
private BigDecimal minimumBalanceChargeAmount;
|
||||
|
||||
@Column(name = "minimum_balance_charge_for_cheque_issue")
|
||||
private BigDecimal minimumBalanceChargeForChequeIssue;
|
||||
|
||||
@Column(name = "minimum_balance_charge_method")
|
||||
private String minimumBalanceChargeMethod;
|
||||
|
||||
@Column(name = "months_after_min_balance_charge_calculate")
|
||||
private Integer monthsAfterMinBalanceChargeCalculate;
|
||||
|
||||
@Column(name = "for_cheque_issue")
|
||||
private BigDecimal forChequeIssue;
|
||||
|
||||
@Column(name = "for_cheque_issue_avg")
|
||||
private BigDecimal forChequeIssueAvg;
|
||||
|
||||
@Column(name = "for_withdrawal_slip")
|
||||
private BigDecimal forWithdrawalSlip;
|
||||
|
||||
@Column(name = "for_withdrawal_slip_avg")
|
||||
private BigDecimal forWithdrawalSlipAvg;
|
||||
|
||||
@Column(name = "calculate_daily_against_clearing_charge")
|
||||
private Boolean calculateDailyAgainstClearingCharge;
|
||||
|
||||
// ---- custom GL account mappings (14) --------------------------------
|
||||
|
||||
@Column(name = "int_receivables_gl_account_id")
|
||||
private Long intReceivablesGlAccountId;
|
||||
|
||||
@Column(name = "int_payable_gl_account_id")
|
||||
private Long intPayableGlAccountId;
|
||||
|
||||
@Column(name = "deaf_int_payable_gl_account_id")
|
||||
private Long deafIntPayableGlAccountId;
|
||||
|
||||
@Column(name = "int_overdue_reserve_account_id")
|
||||
private Long intOverdueReserveAccountId;
|
||||
|
||||
@Column(name = "undebited_interest_account_id")
|
||||
private Long undebitedInterestAccountId;
|
||||
|
||||
@Column(name = "penal_int_cr_gl_account_id")
|
||||
private Long penalIntCrGlAccountId;
|
||||
|
||||
@Column(name = "rd_matured_gl_account_id")
|
||||
private Long rdMaturedGlAccountId;
|
||||
|
||||
@Column(name = "gl_account_id")
|
||||
private Long glAccountId;
|
||||
|
||||
@Column(name = "ic_charge_gl_account_id")
|
||||
private Long icChargeGlAccountId;
|
||||
|
||||
@Column(name = "inoperative_gl_account_id")
|
||||
private Long inoperativeGlAccountId;
|
||||
|
||||
@Column(name = "credit_balance_liability_gl_account_id")
|
||||
private Long creditBalanceLiabilityGlAccountId;
|
||||
|
||||
@Column(name = "credit_balance_asset_gl_account_id")
|
||||
private Long creditBalanceAssetGlAccountId;
|
||||
|
||||
@Column(name = "overdue_accounts_gl_account_id")
|
||||
private Long overdueAccountsGlAccountId;
|
||||
|
||||
@Column(name = "rebate_gl_account_id")
|
||||
private Long rebateGlAccountId;
|
||||
|
||||
public LoanProductCbsExt(final LoanProduct loanProduct) {
|
||||
this.loanProduct = loanProduct;
|
||||
this.loanProductId = loanProduct.getId();
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanproduct.domain;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface LoanProductCbsExtRepository extends JpaRepository<LoanProductCbsExt, Long> {
|
||||
|
||||
/**
|
||||
* A product created before this table existed - or one saved without any legacy field filled in - has
|
||||
* no row here, so callers must handle the empty case rather than assuming one exists.
|
||||
*/
|
||||
Optional<LoanProductCbsExt> findByLoanProductId(Long loanProductId);
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanproduct.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
/**
|
||||
* One row of the legacy "Interest Rate Detail" grid on the loan product form.
|
||||
*
|
||||
* The grid is a fixed four rows - Normal Debit, Normal Credit, Against Clearing and Penalty - each
|
||||
* carrying a Normal and a Special min/max rate plus the period they apply over. It is a child table
|
||||
* rather than twenty-four columns on {@link LoanProductCbsExt} because the interest type reads far
|
||||
* better as data than as part of a column name: against_clearing_special_max_rate and its siblings
|
||||
* are almost unreadable, and any new interest type would mean another migration.
|
||||
*
|
||||
* The rows are fixed today, so {@link #INTEREST_TYPES} is the full set and the table carries a unique
|
||||
* constraint on (product, interest type) - a replayed save updates in place instead of doubling the
|
||||
* grid.
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Table(name = "m_product_loan_cbs_interest_rate", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "loan_product_id", "interest_type" }, name = "mplcir_unq_product_interest_type") })
|
||||
public class LoanProductCbsInterestRate extends AbstractPersistableCustom<Long> {
|
||||
|
||||
/** The grid's rows, in the order the form shows them. */
|
||||
public static final String[] INTEREST_TYPES = { "Normal Debit", "Normal Credit", "Against Clearing", "Penalty" };
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "loan_product_id", nullable = false)
|
||||
private LoanProduct loanProduct;
|
||||
|
||||
@Column(name = "interest_type", nullable = false, length = 30)
|
||||
private String interestType;
|
||||
|
||||
@Column(name = "calculation")
|
||||
private Boolean calculation;
|
||||
|
||||
@Column(name = "normal_min_rate", precision = 9, scale = 6)
|
||||
private BigDecimal normalMinRate;
|
||||
|
||||
@Column(name = "normal_max_rate", precision = 9, scale = 6)
|
||||
private BigDecimal normalMaxRate;
|
||||
|
||||
@Column(name = "special_min_rate", precision = 9, scale = 6)
|
||||
private BigDecimal specialMinRate;
|
||||
|
||||
@Column(name = "special_max_rate", precision = 9, scale = 6)
|
||||
private BigDecimal specialMaxRate;
|
||||
|
||||
@Column(name = "period", length = 20)
|
||||
private String period;
|
||||
|
||||
public LoanProductCbsInterestRate(final LoanProduct loanProduct, final String interestType) {
|
||||
this.loanProduct = loanProduct;
|
||||
this.interestType = interestType;
|
||||
}
|
||||
|
||||
/** True when the officer left this row untouched, so it need not be persisted. */
|
||||
public boolean isEmpty() {
|
||||
return !Boolean.TRUE.equals(this.calculation) && this.normalMinRate == null && this.normalMaxRate == null
|
||||
&& this.specialMinRate == null && this.specialMaxRate == null && (this.period == null || this.period.isBlank());
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanproduct.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface LoanProductCbsInterestRateRepository extends JpaRepository<LoanProductCbsInterestRate, Long> {
|
||||
|
||||
List<LoanProductCbsInterestRate> findByLoanProductIdOrderById(Long loanProductId);
|
||||
|
||||
LoanProductCbsInterestRate findByLoanProductIdAndInterestType(Long loanProductId, String interestType);
|
||||
}
|
||||
Reference in New Issue
Block a user