update loan product code based on new requirement

This commit is contained in:
Nitesh Yadav
2026-05-14 16:10:06 +05:30
parent d0370781e8
commit 8758b9222f
7 changed files with 199 additions and 9 deletions
@@ -440,7 +440,7 @@
}
@if (loanProduct.inArrearsTolerance) {
<div class="flex-fill layout-row">
<span class="flex-40">{{ 'labels.inputs.Arrears tolerance' | translate }}:</span>
<span class="flex-40">Allowed pending EMI amount:</span>
<span class="flex-60">{{ loanProduct.inArrearsTolerance }}</span>
</div>
}
@@ -720,7 +720,7 @@
<span class="flex-60">{{ loanProduct.allowAttributeOverrides.interestCalculationPeriodType | yesNo }}</span>
</div>
<div class="flex-fill layout-row">
<span class="flex-40">{{ 'labels.inputs.Arrears tolerance' | translate }}:</span>
<span class="flex-40">Allowed pending EMI amount:</span>
<span class="flex-60">{{ loanProduct.allowAttributeOverrides.inArrearsTolerance | yesNo }}</span>
</div>
<div class="flex-fill layout-row">
@@ -203,7 +203,14 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
incomeFromGoodwillCreditPenaltyAccountId: accountingMappings.incomeFromGoodwillCreditPenaltyAccount?.id || '',
receivableInterestAccountId: accountingMappings.receivableInterestAccount?.id || '',
receivableFeeAccountId: accountingMappings.receivableFeeAccount?.id || '',
receivablePenaltyAccountId: accountingMappings.receivablePenaltyAccount?.id || ''
receivablePenaltyAccountId: accountingMappings.receivablePenaltyAccount?.id || '',
intReceivablesGlAccountId: accountingMappings.intReceivablesGlAccount?.id || '',
intPayableGlAccountId: accountingMappings.intPayableGlAccount?.id || '',
deafIntPayableGlAccountId: accountingMappings.deafIntPayableGlAccount?.id || '',
intOverdueReserveAccountId: accountingMappings.intOverdueReserveAccount?.id || '',
undebitedInterestAccountId: accountingMappings.undebitedInterestAccount?.id || '',
penalIntCrGlAccountId: accountingMappings.penalIntCrGlAccount?.id || '',
rdMaturedGlAccountId: accountingMappings.rdMaturedGlAccount?.id || ''
});
if (this.loanProductsTemplate.paymentChannelToFundSourceMappings) {
@@ -271,7 +278,14 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
'incomeFromGoodwillCreditPenaltyAccountId',
'receivableInterestAccountId',
'receivableFeeAccountId',
'receivablePenaltyAccountId'
'receivablePenaltyAccountId',
'intReceivablesGlAccountId',
'intPayableGlAccountId',
'deafIntPayableGlAccountId',
'intOverdueReserveAccountId',
'undebitedInterestAccountId',
'penalIntCrGlAccountId',
'rdMaturedGlAccountId'
];
commonFields.forEach((field) => {
if (!this.loanProductAccountingForm.contains(field)) {
@@ -690,6 +704,38 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
options: this.assetAccountData,
required: true,
accrualOnly: true
},
{
key: 'intReceivablesGlAccountId',
label: 'Int. Receivables GL A/c',
inputLabel: 'Int. Receivables GL A/c',
controlName: 'intReceivablesGlAccountId',
options: this.assetAccountData,
required: false
},
{
key: 'deafIntPayableGlAccountId',
label: 'Deaf Int. Payble GL A/c',
inputLabel: 'Deaf Int. Payble GL A/c',
controlName: 'deafIntPayableGlAccountId',
options: this.assetAccountData,
required: false
},
{
key: 'intOverdueReserveAccountId',
label: 'Int. Overdue Reserve A/c (AS)',
inputLabel: 'Int. Overdue Reserve A/c',
controlName: 'intOverdueReserveAccountId',
options: this.assetAccountData,
required: false
},
{
key: 'rdMaturedGlAccountId',
label: 'RD Matured GL A/c',
inputLabel: 'RD Matured GL A/c',
controlName: 'rdMaturedGlAccountId',
options: this.assetAccountData,
required: false
}
],
otherMappingsControlName: 'assetsOtherGlMappings',
@@ -798,6 +844,14 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
options: this.incomeAccountData,
required: true,
deferredBuyDownOnly: true
},
{
key: 'penalIntCrGlAccountId',
label: 'Penal Int. Cr. GL A/c',
inputLabel: 'Penal Int. Cr. GL A/c',
controlName: 'penalIntCrGlAccountId',
options: this.incomeAccountData,
required: false
}
],
otherMappingsControlName: 'incomeOtherGlMappings',
@@ -876,6 +930,22 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
options: this.liabilityAccountData,
required: true,
deferredOnly: true
},
{
key: 'intPayableGlAccountId',
label: 'Int. Payable GL A/c',
inputLabel: 'Int. Payable GL A/c',
controlName: 'intPayableGlAccountId',
options: this.liabilityAccountData,
required: false
},
{
key: 'undebitedInterestAccountId',
label: 'UnDebited Interest A/c (LI)',
inputLabel: 'UnDebited Interest A/c',
controlName: 'undebitedInterestAccountId',
options: this.liabilityAccountData,
required: false
}
],
otherMappingsControlName: 'liabilitiesOtherGlMappings',
@@ -91,6 +91,67 @@
</div>
</div>
<!-- Interest Information -->
<div class="lpd-section">
<div class="lpd-section__header">
<i class="fas fa-percentage"></i>
<h3>Interest Information</h3>
</div>
<div class="lpd-grid">
<mat-form-field appearance="outline" class="lpd-field">
<mat-label>Debit Int. Calculation</mat-label>
<mat-select formControlName="debitIntCalculation">
@for (opt of yesNoOptions; track opt.value) {
<mat-option [value]="opt.value">{{ opt.label }}</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="lpd-field">
<mat-label>Separate Penal Int.</mat-label>
<mat-select formControlName="separatePenalInterest">
@for (opt of yesNoOptions; track opt.value) {
<mat-option [value]="opt.value">{{ opt.label }}</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="lpd-field">
<mat-label>Credit Int. Calculation</mat-label>
<mat-select formControlName="creditIntCalculation">
@for (opt of yesNoOptions; track opt.value) {
<mat-option [value]="opt.value">{{ opt.label }}</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="lpd-field">
<mat-label>Sub A/c Type Balance</mat-label>
<mat-select formControlName="subAccountTypeBalance">
@for (opt of yesNoOptions; track opt.value) {
<mat-option [value]="opt.value">{{ opt.label }}</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="lpd-field">
<mat-label>Final Int. Rounding</mat-label>
<mat-select formControlName="finalIntRounding">
@for (opt of yesNoOptions; track opt.value) {
<mat-option [value]="opt.value">{{ opt.label }}</mat-option>
}
</mat-select>
</mat-form-field>
@if (loanProductDetailsForm.get('finalIntRounding')?.value) {
<mat-form-field appearance="outline" class="lpd-field">
<mat-label>Rounding UpTo</mat-label>
<input matInput type="number" formControlName="roundingUpTo" min="0" />
</mat-form-field>
}
</div>
</div>
<!-- Product Classification + GL Account — combined section -->
<div class="lpd-section">
<div class="lpd-section__header">
@@ -61,6 +61,15 @@ export class LoanProductDetailsStepComponent implements OnInit {
const mappingOptions = this.loanProductsTemplate?.accountingMappingOptions ?? {};
this.assetAccountOptions = mappingOptions.assetAccountOptions ?? [];
this.liabilityAccountOptions = mappingOptions.liabilityAccountOptions ?? [];
this.loanProductDetailsForm.patchValue({
debitIntCalculation: this.loanProductsTemplate.debitIntCalculation ?? false,
separatePenalInterest: this.loanProductsTemplate.separatePenalInterest ?? false,
creditIntCalculation: this.loanProductsTemplate.creditIntCalculation ?? false,
subAccountTypeBalance: this.loanProductsTemplate.subAccountTypeBalance ?? false,
finalIntRounding: this.loanProductsTemplate.finalIntRounding ?? false,
roundingUpTo: this.loanProductsTemplate.roundingUpTo ?? null
});
}
/** Product Classification data */
@@ -121,6 +130,11 @@ export class LoanProductDetailsStepComponent implements OnInit {
return this.productTypeGroups.find((g) => g.id === group)?.label ?? '';
}
readonly yesNoOptions = [
{ value: true, label: 'YES' },
{ value: false, label: 'NO' }
];
createLoanProductDetailsForm() {
this.loanProductDetailsForm = this.formBuilder.group({
name: [
@@ -137,7 +151,13 @@ export class LoanProductDetailsStepComponent implements OnInit {
productTypeGroup: [''],
productTypeSubGroup: [''],
glClassification: ['asset'],
glAccount: ['']
glAccount: [''],
debitIntCalculation: [false],
separatePenalInterest: [false],
creditIntCalculation: [false],
subAccountTypeBalance: [false],
finalIntRounding: [false],
roundingUpTo: [null]
});
// Auto-set GL based on product type group
@@ -163,7 +163,7 @@
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>{{ 'labels.inputs.Arrears tolerance' | translate }}</mat-label>
<mat-label>Allowed pending EMI amount</mat-label>
<input
type="number"
min="0"
@@ -1328,7 +1328,7 @@
</div>
<div class="lps-checkbox-row">
<mat-checkbox labelPosition="before" formControlName="inArrearsTolerance">
{{ 'labels.inputs.Arrears tolerance' | translate }}
Allowed pending EMI amount
</mat-checkbox>
</div>
<div class="lps-checkbox-row">
@@ -413,4 +413,37 @@
</mat-form-field>
</div>
</div>
<!-- Account Behaviour -->
<div class="lpt-section">
<div class="lpt-section-header">
<i class="fas fa-toggle-on lpt-section-icon"></i>
<h3>Account Behaviour</h3>
</div>
<div class="lpt-grid">
<mat-form-field appearance="outline">
<mat-label>Debit Balance Allow</mat-label>
<mat-select formControlName="debitBalanceAllow">
<mat-option [value]="true">YES</mat-option>
<mat-option [value]="false">NO</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Allow Debit Trans After Due Date</mat-label>
<mat-select formControlName="allowDebitTransAfterDueDate">
<mat-option [value]="true">YES</mat-option>
<mat-option [value]="false">NO</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Branch Level A/c Type</mat-label>
<mat-select formControlName="branchLevelAccountType">
<mat-option [value]="true">YES</mat-option>
<mat-option [value]="false">NO</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</form>
@@ -108,7 +108,10 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
repaymentFrequencyType: this.loanProductsTemplate.repaymentFrequencyType.id,
minimumDaysBetweenDisbursalAndFirstRepayment:
this.loanProductsTemplate.minimumDaysBetweenDisbursalAndFirstRepayment,
repaymentStartDateType: this.loanProductsTemplate.repaymentStartDateType.id || 1
repaymentStartDateType: this.loanProductsTemplate.repaymentStartDateType.id || 1,
debitBalanceAllow: this.loanProductsTemplate.debitBalanceAllow ?? false,
allowDebitTransAfterDueDate: this.loanProductsTemplate.allowDebitTransAfterDueDate ?? false,
branchLevelAccountType: this.loanProductsTemplate.branchLevelAccountType ?? false
});
if (this.loanProductsTemplate.allowApprovedDisbursedAmountsOverApplied) {
@@ -207,7 +210,10 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
[]
],
repaymentStartDateType: [1],
fixedLength: [null]
fixedLength: [null],
debitBalanceAllow: [false],
allowDebitTransAfterDueDate: [false],
branchLevelAccountType: [false]
});
}