-
-
-
-
-
-
-
-
-
- @for (genGroup of slabGroups; track $index) {
-
-
{{ interestSlabDefinitions[$index].label }}
-
-
- }
-
-
-
-
+
diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.scss b/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.scss
index bda5c6392..d4f7af28d 100644
--- a/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.scss
+++ b/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.scss
@@ -199,175 +199,42 @@ $shadow-hover: 0 4px 12px rgb(37 99 235 / 10%);
padding: 8px 4px;
}
-// ─── Interest Rate Slabs — Option C (2-column grid) ──────────────────────────
-.lpt-slab-c {
+// ─── Interest Rate Detail table (legacy Page 1 grid) ─────────────────────────
+.lpt-ird-table-wrap {
padding: 16px 24px 20px;
- display: flex;
- flex-direction: column;
- gap: 0;
+ overflow-x: auto;
}
-// Particular row
-.lpt-slab-c-particular {
- display: flex;
- align-items: center;
- gap: 14px;
- padding-bottom: 14px;
- border-bottom: 1px solid $border;
- margin-bottom: 12px;
- flex-wrap: wrap;
-}
-
-.lpt-slab-c-particular-label {
- font-size: 12px;
- font-weight: 700;
- color: $text-secondary;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- white-space: nowrap;
-}
-
-.lpt-slab-c-name-input {
- flex: 1;
- max-width: 320px;
- padding: 7px 12px;
- border: 1px solid $border;
- border-radius: 8px;
- font-size: 13.5px;
- font-weight: 600;
- color: $text-primary;
- background: $surface;
- outline: none;
- transition:
- border-color 0.15s,
- box-shadow 0.15s;
-
- &::placeholder {
- color: #b0b8c4;
- font-weight: 400;
- }
-
- &:focus {
- border-color: $primary;
- box-shadow: 0 0 0 3px rgb(37 99 235 / 10%);
- }
-}
-
-// General / Special tab toggle
-.lpt-slab-tabs {
- display: flex;
- gap: 6px;
- margin-left: auto;
-}
-
-.lpt-slab-tab {
- display: inline-flex;
- align-items: center;
- gap: 6px;
- padding: 6px 16px;
- border: 1.5px solid $border;
- border-radius: 20px;
- background: $surface;
+.lpt-ird-table {
+ width: 100%;
+ border-collapse: collapse;
font-size: 12.5px;
- font-weight: 600;
- color: $text-secondary;
- cursor: pointer;
- transition: all 0.15s;
- i {
+ th,
+ td {
+ border: 1px solid $border;
+ padding: 6px 8px;
+ text-align: center;
+ }
+
+ thead th {
+ background: $surface-alt;
+ font-weight: 700;
+ color: $text-secondary;
+ text-transform: uppercase;
+ letter-spacing: 0.03em;
font-size: 11px;
}
-
- &:hover {
- border-color: $primary;
- color: $primary;
- }
-
- &--active {
- background: $primary;
- border-color: $primary;
- color: $surface;
- box-shadow: 0 2px 8px rgb(37 99 235 / 25%);
- }
}
-// 2-column slab grid
-.lpt-slab-c-grid {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 8px 16px;
-
- @media (width <= 540px) {
- grid-template-columns: 1fr;
- }
-}
-
-.lpt-slab-c-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 10px;
- padding: 8px 12px;
- border: 1px solid $border;
- border-radius: 8px;
- background: $surface;
- transition:
- border-color 0.15s,
- box-shadow 0.15s;
-
- &:focus-within {
- border-color: $primary;
- box-shadow: 0 0 0 3px rgb(37 99 235 / 8%);
- }
-}
-
-// General + Special pair inside each card
-.lpt-slab-c-rate-pair {
- display: flex;
- gap: 8px;
- align-items: center;
-}
-
-.lpt-slab-c-rate-field {
- display: flex;
- align-items: center;
- gap: 4px;
-}
-
-.lpt-slab-c-rate-label {
- font-size: 10px;
- font-weight: 700;
- color: $primary;
- background: #eff6ff;
- padding: 2px 5px;
- border-radius: 4px;
+.lpt-ird-type {
+ text-align: left !important;
+ font-weight: 600;
+ color: $text-primary;
white-space: nowrap;
-
- &--special {
- color: #92400e;
- background: #fef9c3;
- }
}
-.lpt-slab-c-range {
- font-size: 12.5px;
- font-weight: 500;
- color: $text-label;
- flex: 1;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-// Input + suffix wrapper
-.lpt-slab-c-input-wrap {
- display: flex;
- align-items: center;
- gap: 4px;
- flex-shrink: 0;
-}
-
-.lpt-slab-c-input {
+.lpt-ird-input {
width: 70px;
padding: 4px 6px;
border: 1px solid $border;
@@ -379,79 +246,26 @@ $shadow-hover: 0 4px 12px rgb(37 99 235 / 10%);
background: $surface-alt;
outline: none;
transition: border-color 0.15s;
- appearance: textfield;
-
- &::-webkit-outer-spin-button,
- &::-webkit-inner-spin-button {
- appearance: none;
- }
&:focus {
border-color: $primary;
background: $primary-light;
}
-
- &--fixed {
- width: 90px;
- }
}
-.lpt-slab-c-suffix {
- font-size: 12px;
- font-weight: 700;
- color: $text-secondary;
- user-select: none;
-
- &--special {
- color: #92400e;
- }
-}
-
-.lpt-slab-c-input--special {
- &:focus {
- border-color: #f59e0b;
- background: #fef9c3;
- }
-}
-
-.lpt-slab-c-error {
- font-size: 10px;
- color: #ef4444;
-}
-
-// Fixed Interest Rate row (below grid)
-.lpt-slab-c-fixed {
- display: flex;
- align-items: center;
- gap: 20px;
- margin: 12px -24px -20px;
- padding: 12px 16px;
- border-top: 2px dashed $primary-border;
- background: $primary-light;
- border-radius: 0 0 $radius-card $radius-card;
- padding-left: 24px;
- padding-right: 24px;
-}
-
-.lpt-slab-c-fixed-toggle {
- display: flex;
- align-items: center;
- gap: 8px;
- cursor: pointer;
+.lpt-ird-select {
+ width: 100%;
+ min-width: 90px;
+ padding: 4px 6px;
+ border: 1px solid $border;
+ border-radius: 6px;
font-size: 13px;
font-weight: 600;
- color: $primary;
- user-select: none;
+ color: $text-primary;
+ background: $surface;
+ outline: none;
- i {
- font-size: 12px;
- opacity: 0.7;
+ &:focus {
+ border-color: $primary;
}
}
-
-.lpt-slab-c-checkbox {
- accent-color: $primary;
- width: 15px;
- height: 15px;
- cursor: pointer;
-}
diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.ts b/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.ts
index 9e457b6d8..baf888790 100644
--- a/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.ts
+++ b/src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.ts
@@ -57,24 +57,23 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
repaymentFrequencyTypeData: any;
repaymentStartDateTypeOptions: any;
- readonly interestSlabDefinitions = [
- { label: 'Upto 10,000', maxAmount: 10000 },
- { label: 'Upto 25,000', maxAmount: 25000 },
- { label: 'Upto 1,00,000', maxAmount: 100000 },
- { label: 'Upto 2,00,000', maxAmount: 200000 },
- { label: 'Upto 5,00,000', maxAmount: 500000 },
- { label: 'Upto 10,00,000', maxAmount: 1000000 },
- { label: 'Upto 15,00,000', maxAmount: 1500000 },
- { label: 'Upto 20,00,000', maxAmount: 2000000 },
- { label: 'Upto 25,00,000', maxAmount: 2500000 },
- { label: 'More than 25,00,000', maxAmount: null }
+ // Legacy "Interest Rate Detail" table — 4 interest types x Normal/Special category x Min/Max Rate x Period
+ readonly interestRateDetailTypes = [
+ 'Normal Debit',
+ 'Normal Credit',
+ 'Against Clearing',
+ 'Penalty'
];
- interestRateSlabsArray: FormArray;
- specialSlabsArray: FormArray;
- fixedRateGroup: FormGroup;
- particularLabel = new FormControl('');
- activeSlabTab: 'general' | 'special' = 'general';
+ readonly interestRateDetailPeriods = [
+ 'DAILY',
+ 'MONTHLY',
+ 'QUARTERLY',
+ 'HALF YEARLY',
+ 'YEARLY'
+ ];
+
+ interestRateDetailArray: FormArray;
constructor() {
this.createLoanProductTermsForm();
@@ -134,35 +133,32 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
}
createLoanProductTermsForm() {
- this.interestRateSlabsArray = new FormArray(
- this.interestSlabDefinitions.map(
+ this.interestRateDetailArray = new FormArray(
+ this.interestRateDetailTypes.map(
() =>
new FormGroup({
- interestRate: new FormControl(null, [
+ calculation: new FormControl(false),
+ normalMinRate: new FormControl(null, [
Validators.min(0),
Validators.max(100)
- ])
+ ]),
+ normalMaxRate: new FormControl(null, [
+ Validators.min(0),
+ Validators.max(100)
+ ]),
+ specialMinRate: new FormControl(null, [
+ Validators.min(0),
+ Validators.max(100)
+ ]),
+ specialMaxRate: new FormControl(null, [
+ Validators.min(0),
+ Validators.max(100)
+ ]),
+ period: new FormControl('')
})
)
);
- this.specialSlabsArray = new FormArray(
- this.interestSlabDefinitions.map(
- () =>
- new FormGroup({
- interestRate: new FormControl(null, [
- Validators.min(0),
- Validators.max(100)
- ])
- })
- )
- );
-
- this.fixedRateGroup = new FormGroup({
- hasFixed: new FormControl(false),
- fixedAmount: new FormControl({ value: null, disabled: true }, [Validators.min(0)])
- });
-
this.loanProductTermsForm = this.formBuilder.group({
isLinkedToFloatingInterestRates: [false],
allowApprovedDisbursedAmountsOverApplied: [false],
@@ -287,15 +283,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
}
});
- this.fixedRateGroup.get('hasFixed').valueChanges.subscribe((hasFixed: boolean) => {
- if (hasFixed) {
- this.fixedRateGroup.get('fixedAmount').enable();
- } else {
- this.fixedRateGroup.get('fixedAmount').disable();
- this.fixedRateGroup.get('fixedAmount').setValue(null);
- }
- });
-
this.zeroInterest.valueChanges.subscribe((zeroInterest) => {
if (zeroInterest) {
this.loanProductTermsForm.get('minInterestRatePerPeriod').patchValue(0);
@@ -322,16 +309,8 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
});
}
- get slabGroups(): FormGroup[] {
- return this.interestRateSlabsArray.controls as FormGroup[];
- }
-
- get activeSlabGroups(): FormGroup[] {
- return this.interestRateSlabsArray.controls as FormGroup[];
- }
-
- get specialSlabGroups(): FormGroup[] {
- return this.specialSlabsArray.controls as FormGroup[];
+ get interestRateDetailGroups(): FormGroup[] {
+ return this.interestRateDetailArray.controls as FormGroup[];
}
get loanProductTerms() {
@@ -349,15 +328,10 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
minInterestRatePerPeriod: normalizeDecimal(formValue.minInterestRatePerPeriod),
interestRatePerPeriod: normalizeDecimal(formValue.interestRatePerPeriod),
maxInterestRatePerPeriod: normalizeDecimal(formValue.maxInterestRatePerPeriod),
- interestRateSlabs: this.interestRateSlabsArray.getRawValue().map((slab, i) => ({
- maxAmount: this.interestSlabDefinitions[i].maxAmount,
- label: this.interestSlabDefinitions[i].label,
- interestRate: slab.interestRate
- })),
- fixedRate: (() => {
- const fr = this.fixedRateGroup.getRawValue();
- return fr.hasFixed ? fr.fixedAmount : null;
- })()
+ interestRateDetail: this.interestRateDetailArray.getRawValue().map((row, i) => ({
+ interestType: this.interestRateDetailTypes[i],
+ ...row
+ }))
};
}
diff --git a/src/app/products/loan-products/loan-products.ts b/src/app/products/loan-products/loan-products.ts
index 884b0a087..2d31b2b24 100644
--- a/src/app/products/loan-products/loan-products.ts
+++ b/src/app/products/loan-products/loan-products.ts
@@ -9,6 +9,246 @@
import { Injectable, inject } from '@angular/core';
import { SettingsService } from 'app/settings/settings.service';
+// Custom, UI-only fields grafted onto the loan product form to mirror the legacy
+// "Account Type Creation" screen. Fineract's LoanProductDataValidator rejects any
+// unrecognised parameter, so these are stripped from the payload until a backend
+// mechanism (e.g. a linked Data Table) exists to persist them.
+const CUSTOM_UI_ONLY_FIELDS: string[] = [
+ // Details step — classification & legacy header fields
+ 'productTypeGroup',
+ 'productTypeSubGroup',
+ 'debitIntCalculation',
+ 'separatePenalInterest',
+ 'creditIntCalculation',
+ 'subAccountTypeBalance',
+ 'finalIntRounding',
+ 'roundingUpTo',
+ 'accountTypeCode',
+ 'micrTransactionCode',
+ 'reservedEcsSerialNumber',
+ 'reverseEcsNumber',
+ 'lockChequeInfoEnabled',
+ 'lockPageTwoInfoEnabled',
+ 'computerizationDate',
+ 'chequePrintDescription',
+ 'posAccountTypeDescription',
+ 'pfmsAccountType',
+ 'renewalDateAddMonths',
+ 'documentRenewalDateAddMonths',
+ 'ppsLimit',
+ 'isWriteOffAccountType',
+ 'writeOffAccountTypeCode',
+ 'renewalGraceDays',
+ // Settings step — Cheque Book Settings
+ 'chequeBookIssueEnabled',
+ 'chequeValidationRequired',
+ 'isFirstChequeBookFree',
+ 'chequePrintingAccountType',
+ 'allowWithdrawalSlipUsage',
+ 'maintainChequeBookStockRegistry',
+ 'freeChequeBooksPerYear',
+ 'allowCreditByChequeNumber',
+ 'creditChequeValidationRequired',
+ 'graceDaysForStockStatement',
+ // Settings step — Additional Product Settings
+ 'accountTypeActiveForTransactions',
+ 'subTypeActivityEnabled',
+ 'accountOpeningCharges',
+ 'maximumGoldLoanLimit',
+ 'lastAccountNumberOpened',
+ 'customerTerminationAllowed',
+ 'chargesForCashCreditAboveLimit',
+ 'deathInterestGLAccount',
+ 'startingLedgerNumber',
+ 'endingLedgerNumber',
+ 'currentLedgerNumber',
+ 'remittanceAccountNumber',
+ 'isNonResidentIndianAccount',
+ 'debitClearingGLAccount',
+ 'missedCallAlertServiceActive',
+ 'standingInstructionChargeGLAccount',
+ 'standingInstructionDebitChargeSkipOption',
+ 'openingBalanceMultiplierForRemittanceCharges',
+ 'goldLoanPacketNumberWithYearEnabled',
+ 'accountMoveToInoperativeEnabled',
+ 'generateGlDiffEntryEnabled',
+ 'subTypeWiseGlBalanceGenerationEnabled',
+ 'validateBeforeDeletingDebitEntryEnabled',
+ 'rcFileConceptEnabled',
+ 'accountCloseZeroBalanceInOpenDayProcess',
+ 'accountCloseZeroBalanceAtSubledgerTranEntry',
+ 'limitEnhancementAgainstClearingScreenDisplayEnabled',
+ 'advanceInterestParameterInLedgerEnabled',
+ 'vehicleDetailInMasterEnabled',
+ 'deletedChequeIssueEnabled',
+ 'dpReduceInDocumentRenewalDateEnabled',
+ 'dpReduceInRenewalDateEnabled',
+ 'autoCloseAtDayEndEnabled',
+ 'loanRateFromMasterEnabled',
+ 'chequeShortName',
+ 'statementPrintEnabled',
+ 'neslCode',
+ // Settings step — Interest Related Parameters
+ 'drawingPowerAndLimitGenerationProcedure',
+ 'advancesInterestCalculationMethod',
+ 'againstInterestCalculationEnabled',
+ 'dayWiseAgainstClearingInterestRounding',
+ 'interestCalculationOneFourthMethod',
+ 'againstClearingInterestProcedureType',
+ 'considerDebitClosingAmountForAgainstClearing',
+ 'interestRoundingMethod',
+ 'penaltyInterestCalculationEnabled',
+ 'penaltyInterestCalculationMethod',
+ 'penaltyInterestProcedureNumber',
+ 'overdrawnInterestCalculationMethod',
+ 'calculateOverdrawnInterestAfterRenewal',
+ 'interestOnCreditBalance',
+ 'penaltyInterestDateDifferentThanRegularInterest',
+ 'fixedDepositOverdraftCertificateSortOrder',
+ 'useDocumentSubmissionDateForInterest',
+ 'loanManagementSystemRenewalPenaltyActive',
+ 'minimumNormalInterestAmount',
+ 'minimumInterestCalculationMethod',
+ 'minimumAgainstClearingInterestAmount',
+ 'limitIncreaseUptoInterestAmountInInterestCalculation',
+ 'minimumPenaltyInterestAmount',
+ 'daysForLimitIncreaseUptoInterestAmount',
+ 'additionalInterestRateForFixedDepositOverdraft',
+ 'considerDdPayorderInAgainstClearingInterestCalculation',
+ 'graceDaysAfterRenewDate',
+ 'applyUndebitedInterestConceptEnabled',
+ 'interestRegisterPrintFormatType',
+ 'normalGraceDaysAfterOverdue',
+ 'allowAgainstClearingEntry',
+ 'allowNoBalanceEntry',
+ 'fixedDepositOverdraftPenaltyInterestCombinedWithNormalInterest',
+ 'allowNoBalanceEntryWithPassword',
+ 'undebitedSimpleInterestAccountWise',
+ 'dailyInterestCalculationEnabled',
+ 'dailyInterestCalculationStartDate',
+ 'nonPerformingAssetPenalInterestRateUpdate',
+ 'nonPerformingAssetPenalInterestRate',
+ 'fixedDepositOverdraftPenalInterestRateUpdateInBranchProcess',
+ 'addPenalInterestRate',
+ 'atyp14SimpleInterestEnabled',
+ 'fixedDepositOverdraftMarginType',
+ 'checkMasterDetailEditedPassingPendingEnabled',
+ 'creditDebitInterestCalculationSeparateEnabled',
+ 'onTimeInterestProvisionEnabled',
+ 'checkAgainstClearingEnabled',
+ 'gstOnPenaltyEnabled',
+ 'penaltyInterestGraceDays',
+ 'overdrawnInterestRate',
+ 'calculateDailyLimitEnhancementTodEnabled',
+ 'fixedDepositOverdraftMultipleInterestRateEnabled',
+ 'graceDaysAfterOverdueForMoratorium',
+ // Settings step — Credit Bureau Settings (CIBIL)
+ 'cibilAccountType',
+ 'cibilCommercialAccountType',
+ 'highmarkAccountType',
+ 'highmarkCommercialAccountType',
+ 'experianAccountType',
+ 'experianCommercialAccountType',
+ 'equifaxAccountType',
+ 'equifaxCommercialAccountType',
+ // Settings step — RBI Compliance & Product Category
+ 'loanProductCategory',
+ 'penalChargeMethod',
+ 'isFloatingRate',
+ 'foreclosureChargesApplicable',
+ 'keyFactStatementEnabled',
+ 'annualPercentageRateCalculationEnabled',
+ // Settings step — Channel & Transaction Limits
+ 'isMobileAppEnabled',
+ 'isAtmEnabled',
+ 'atmYearlyChargeEnabled',
+ 'atmMinimumBalance',
+ 'emailActiveEnabled',
+ 'isImpsEnabled',
+ 'isUpiEnabled',
+ 'isPosEnabled',
+ 'isBbpsEnabled',
+ 'interBankLimitPerDay',
+ 'interBankLimitPerTransaction',
+ 'neftRtgsLimitPerDay',
+ 'neftRtgsLimitPerTransaction',
+ 'neftCutoffLimit',
+ 'rtgsCutoffLimit',
+ 'neftRtgsMinimumBalance',
+ 'isChargeRequiredNeftRtgsCbs',
+ 'isChargeRequiredNeftRtgsMobile',
+ 'impsLimitPerDay',
+ 'impsLimitPerTransaction',
+ 'impsLimitPerMonth',
+ 'impsMinLimit',
+ 'impsMonthlyTransactionCount',
+ // Settings step — POS Facility & ATM CSV Settings
+ 'maxPerTransactionLimitAtm',
+ 'maxDayTransactionLimitAtm',
+ 'maxPerTransactionLimitPos',
+ 'maxDayTransactionLimitPos',
+ 'maxPerTransactionLimitEcom',
+ 'maxDayTransactionLimitEcom',
+ 'maxPerTransactionLimitUpi',
+ 'maxDayTransactionLimitUpi',
+ 'atmCsvProductCode',
+ 'atmCsvTypeCode',
+ // Settings step — Auto Interest Post Parameters
+ 'autoInterestPostType',
+ 'autoInterestPostWhen',
+ 'autoInterestPostFixDay',
+ 'autoLastInterestDate',
+ // Settings step — Foreclosure / Early Account Closure
+ 'calculateEarlyAccountCloseCharge',
+ 'earlyAccountCloseCharge',
+ 'earlyAccountClosePeriodInMonths',
+ // Terms step
+ 'debitBalanceAllow',
+ 'allowDebitTransAfterDueDate',
+ 'branchLevelAccountType',
+ 'interestRateDetail',
+ // Charges step — legacy cheque / standing instruction / minimum balance charges
+ 'chequeBookChargeEnabled',
+ 'chequeReturnChargeEnabled',
+ 'icChargeDebitEnabled',
+ 'cashBundleChargeEnabled',
+ 'cashBundleChargeWithPanLimit',
+ 'perChequeEntryCharge',
+ 'perChequeEntryServiceCharge',
+ 'perInwardChequeEntryCharge',
+ 'perOutwardChequeEntryCharge',
+ 'creditorStandingInstructionFailCharge',
+ 'debtorStandingInstructionFailCharge',
+ 'minimumBalanceCheckingType',
+ 'autoMinimumBalanceCharge',
+ 'calculateDailyMinimumBalanceCharges',
+ 'minimumBalanceChargeEnabled',
+ 'minimumBalanceChargeAmount',
+ 'minimumBalanceChargeForChequeIssue',
+ 'minimumBalanceChargeMethod',
+ 'monthsAfterMinBalanceChargeCalculate',
+ 'forChequeIssue',
+ 'forChequeIssueAvg',
+ 'forWithdrawalSlip',
+ 'forWithdrawalSlipAvg',
+ 'calculateDailyAgainstClearingCharge',
+ // Accounting step — custom GL account mappings
+ 'intReceivablesGlAccountId',
+ 'intPayableGlAccountId',
+ 'deafIntPayableGlAccountId',
+ 'intOverdueReserveAccountId',
+ 'undebitedInterestAccountId',
+ 'penalIntCrGlAccountId',
+ 'rdMaturedGlAccountId',
+ 'glAccountId',
+ 'icChargeGlAccountId',
+ 'inoperativeGlAccountId',
+ 'creditBalanceLiabilityGlAccountId',
+ 'creditBalanceAssetGlAccountId',
+ 'overdueAccountsGlAccountId',
+ 'rebateGlAccountId'
+];
+
@Injectable({
providedIn: 'root'
})
@@ -49,6 +289,9 @@ export class LoanProducts {
delete loanProduct.allowAttributeConfiguration;
delete loanProduct.advancedAccountingRules;
+ // Remove custom, UI-only fields not yet recognised by the Fineract backend
+ CUSTOM_UI_ONLY_FIELDS.forEach((field) => delete loanProduct[field]);
+
// In Fineract, the POST and PUT endpoints for /v1/loanproducts have a typo in the field
// allowPartialPeriodInterestCalculation. Until that is fixed, we need to replace the field name in the payload.
loanProduct.allowPartialPeriodInterestCalculation = loanProduct.allowPartialPeriodInterestCalculation;