feat(loan-products): Gold and Warehouse Receipt product fields with validation
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 - PostgreSQL / test (test-core-1) (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-5) (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 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 Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (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 Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s

- Liquibase 0604 to 0607: columns on m_product_loan_advance_ext for Loan against Gold (LTV cap, purity,
  rate source, weights, appraiser rule, packet prefix, auction notice, revaluation on NPA and its charge,
  partial release, third-party gold, disbursement mode and cash limit, LTV breach alert, auction reserve
  price, redeem before auction) and for Warehouse Receipt (receipt type, WDRA and assay rules, tenure
  within receipt validity, repository pledge, commodity groups, valuation price source, max loan per
  quintal, stock inspection, LTV alert, partial release, disposal notice and reserve price).
- LoanProductAdvanceExt and LoanProductAdvanceExtService: the new fields are accepted, saved and read
  back (so Edit and View can use them).
- Validation on the merged state: the LTV cap must cover the LTV the margin gives, the breach alert may
  not sit below the cap, tenure is at most 12 months, redeem-before-sale cannot be switched off, a gold
  cash disbursement limit is at most 20,000, a warehouse needs a WDRA-registered warehouse and an assay
  certificate, and the receipt type, commodity groups and price source must be known values.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-19 10:55:48 +05:30
co-authored by Claude Sonnet 5.5
parent 0191461102
commit e95e981bcd
7 changed files with 561 additions and 1 deletions
@@ -145,6 +145,116 @@ public class LoanProductAdvanceExt {
@Column(name = "stock_statement_validity_days")
private Integer stockStatementValidityDays;
// ---- Loan against Gold (pledged ornaments) ---------------------------
@Column(name = "gold_max_ltv_pct")
private BigDecimal goldMaxLtvPct;
@Column(name = "gold_min_purity_carat")
private Integer goldMinPurityCarat;
@Column(name = "gold_rate_source")
private String goldRateSource;
@Column(name = "gold_max_per_gram")
private BigDecimal goldMaxPerGram;
@Column(name = "gold_min_net_weight_g")
private BigDecimal goldMinNetWeightG;
@Column(name = "gold_max_net_weight_per_customer_g")
private BigDecimal goldMaxNetWeightPerCustomerG;
@Column(name = "gold_allowed_items")
private String goldAllowedItems;
@Column(name = "gold_appraiser_required")
private Boolean goldAppraiserRequired;
@Column(name = "gold_valuation_certificate_required")
private Boolean goldValuationCertificateRequired;
@Column(name = "gold_max_valuation_per_appraiser")
private BigDecimal goldMaxValuationPerAppraiser;
@Column(name = "gold_packet_prefix")
private String goldPacketPrefix;
@Column(name = "gold_auction_notice_days")
private Integer goldAuctionNoticeDays;
@Column(name = "gold_revalue_on_npa")
private Boolean goldRevalueOnNpa;
@Column(name = "gold_revaluation_charge_applicable")
private Boolean goldRevaluationChargeApplicable;
@Column(name = "gold_partial_release_allowed")
private Boolean goldPartialReleaseAllowed;
@Column(name = "gold_third_party_allowed")
private Boolean goldThirdPartyAllowed;
@Column(name = "gold_disbursement_mode")
private String goldDisbursementMode;
@Column(name = "gold_cash_disbursement_limit")
private BigDecimal goldCashDisbursementLimit;
@Column(name = "gold_ltv_breach_alert_pct")
private BigDecimal goldLtvBreachAlertPct;
@Column(name = "gold_auction_reserve_pct")
private BigDecimal goldAuctionReservePct;
@Column(name = "gold_redeem_before_auction")
private Boolean goldRedeemBeforeAuction;
// ---- Loan against Warehouse Receipt (pledged commodity) ----------------
@Column(name = "wr_max_ltv_pct")
private BigDecimal wrMaxLtvPct;
@Column(name = "wr_receipt_type")
private String wrReceiptType;
@Column(name = "wr_wdra_registered")
private Boolean wrWdraRegistered;
@Column(name = "wr_assay_certificate_required")
private Boolean wrAssayCertificateRequired;
@Column(name = "wr_tenure_within_receipt_validity")
private Boolean wrTenureWithinReceiptValidity;
@Column(name = "wr_pledge_marked_before_disbursement")
private Boolean wrPledgeMarkedBeforeDisbursement;
@Column(name = "wr_commodity_groups")
private String wrCommodityGroups;
@Column(name = "wr_valuation_price_source")
private String wrValuationPriceSource;
@Column(name = "wr_max_loan_per_quintal")
private BigDecimal wrMaxLoanPerQuintal;
@Column(name = "wr_stock_inspection_months")
private Integer wrStockInspectionMonths;
@Column(name = "wr_ltv_breach_alert_pct")
private BigDecimal wrLtvBreachAlertPct;
@Column(name = "wr_partial_release_allowed")
private Boolean wrPartialReleaseAllowed;
@Column(name = "wr_disposal_notice_days")
private Integer wrDisposalNoticeDays;
@Column(name = "wr_disposal_reserve_pct")
private BigDecimal wrDisposalReservePct;
@Column(name = "wr_redeem_before_disposal")
private Boolean wrRedeemBeforeDisposal;
// ---- common eligibility & document checklist (Advances and Loans) ----
@Column(name = "elig_member_required")
private Boolean memberRequired;