@@ -105,7 +105,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
105105 /** Is Multi Disburse Loan */
106106 multiDisburseLoan : any ;
107107 // @Input () loansAccountFormValid: LoansAccountFormValid
108- @Input ( ) loansAccountFormValid : boolean ;
108+ @Input ( ) loansAccountFormValid : boolean = false ;
109109 // @Input collateralOptions: Collateral Options
110110 @Input ( ) collateralOptions : any ;
111111 // @Input loanPrincipal: Loan Principle
@@ -116,7 +116,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
116116 /** Maximum date allowed. */
117117 maxDate = new Date ( 2100 , 0 , 1 ) ;
118118 /** Loans Account Terms Form */
119- loansAccountTermsForm : UntypedFormGroup ;
119+ loansAccountTermsForm : UntypedFormGroup = new UntypedFormGroup ( { } ) ;
120120 /** Term Frequency Type Data */
121121 termFrequencyTypeData : any ;
122122 /** Repayment Frequency Nth Day Type Data */
@@ -259,7 +259,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
259259 'enableInstallmentLevelDelinquency' ,
260260 new UntypedFormControl (
261261 this . loansAccountTermsData . enableInstallmentLevelDelinquency ||
262- this . loanProduct . enableInstallmentLevelDelinquency
262+ this . loanProduct ? .enableInstallmentLevelDelinquency
263263 )
264264 ) ;
265265 }
@@ -397,7 +397,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
397397 'enableInstallmentLevelDelinquency' ,
398398 new UntypedFormControl (
399399 this . loansAccountTermsData . enableInstallmentLevelDelinquency ||
400- this . loanProduct . enableInstallmentLevelDelinquency
400+ this . loanProduct ? .enableInstallmentLevelDelinquency
401401 )
402402 ) ;
403403 }
@@ -437,6 +437,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
437437 this . setAdvancedPaymentStrategyControls ( ) ;
438438 this . setCustomValidators ( ) ;
439439 this . setLoanTermListener ( ) ;
440+ this . setNumericFieldListeners ( ) ;
440441
441442 if ( this . allowAddDisbursementDetails ( ) ) {
442443 this . loansAccountTermsForm . removeControl ( 'maxOutstandingLoanBalance' ) ;
@@ -487,34 +488,34 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
487488 const repaymentFrequencyNthDayType = this . loansAccountTermsForm . get ( 'repaymentFrequencyNthDayType' ) ;
488489 const repaymentFrequencyDayOfWeekType = this . loansAccountTermsForm . get ( 'repaymentFrequencyDayOfWeekType' ) ;
489490
490- this . loansAccountTermsForm . get ( 'repaymentFrequencyType' ) . valueChanges . subscribe ( ( repaymentFrequencyType ) => {
491- repaymentFrequencyNthDayType . setValidators ( null ) ;
492- repaymentFrequencyDayOfWeekType . setValidators ( null ) ;
491+ this . loansAccountTermsForm . get ( 'repaymentFrequencyType' ) ? .valueChanges . subscribe ( ( repaymentFrequencyType ) => {
492+ repaymentFrequencyNthDayType ? .setValidators ( null ) ;
493+ repaymentFrequencyDayOfWeekType ? .setValidators ( null ) ;
493494
494495 setTimeout ( ( ) => {
495- repaymentFrequencyNthDayType . updateValueAndValidity ( ) ;
496- repaymentFrequencyDayOfWeekType . updateValueAndValidity ( ) ;
496+ repaymentFrequencyNthDayType ? .updateValueAndValidity ( ) ;
497+ repaymentFrequencyDayOfWeekType ? .updateValueAndValidity ( ) ;
497498 } ) ;
498499 } ) ;
499500 }
500501
501502 /** Custom Listeners for the form to calculate Loan Term */
502503 setLoanTermListener ( ) {
503- this . loansAccountTermsForm . get ( 'numberOfRepayments' ) . valueChanges . subscribe ( ( numberOfRepayments ) => {
504+ this . loansAccountTermsForm . get ( 'numberOfRepayments' ) ? .valueChanges . subscribe ( ( numberOfRepayments ) => {
504505 const repaymentEvery : number = this . loansAccountTermsForm . value . repaymentEvery ;
505506 this . calculateLoanTerm ( numberOfRepayments , repaymentEvery ) ;
506507 } ) ;
507508
508- this . loansAccountTermsForm . get ( 'repaymentEvery' ) . valueChanges . subscribe ( ( repaymentEvery ) => {
509+ this . loansAccountTermsForm . get ( 'repaymentEvery' ) ? .valueChanges . subscribe ( ( repaymentEvery ) => {
509510 const numberOfRepayments : number = this . loansAccountTermsForm . value . numberOfRepayments ;
510511 this . calculateLoanTerm ( numberOfRepayments , repaymentEvery ) ;
511512 } ) ;
512513
513- this . loansAccountTermsForm . get ( 'loanTermFrequencyType' ) . valueChanges . subscribe ( ( loanTermFrequencyType ) => {
514+ this . loansAccountTermsForm . get ( 'loanTermFrequencyType' ) ? .valueChanges . subscribe ( ( loanTermFrequencyType ) => {
514515 this . loansAccountTermsForm . patchValue ( { repaymentFrequencyType : loanTermFrequencyType } ) ;
515516 } ) ;
516517
517- this . loansAccountTermsForm . get ( 'amortizationType' ) . valueChanges . subscribe ( ( amortizationType ) => {
518+ this . loansAccountTermsForm . get ( 'amortizationType' ) ? .valueChanges . subscribe ( ( amortizationType ) => {
518519 if ( amortizationType === 0 ) {
519520 // Equal Principal Payments
520521 this . loansAccountTermsForm . addControl ( 'fixedPrincipalPercentagePerInstallment' , new UntypedFormControl ( '' ) ) ;
@@ -525,6 +526,38 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
525526 } ) ;
526527 }
527528
529+ /** Prevent negative values in numeric fields */
530+ setNumericFieldListeners ( ) {
531+ const numericFieldsWithMinZero = [
532+ 'graceOnPrincipalPayment' ,
533+ 'graceOnInterestPayment' ,
534+ 'graceOnArrearsAgeing' ,
535+ 'inArrearsTolerance' ,
536+ 'graceOnInterestCharged' ,
537+ 'loanTermFrequency' ,
538+ 'numberOfRepayments' ,
539+ 'repaymentEvery'
540+ ] ;
541+ numericFieldsWithMinZero . forEach ( ( fieldName ) => {
542+ const control = this . loansAccountTermsForm . get ( fieldName ) ;
543+ if ( control ) {
544+ control . valueChanges . subscribe ( ( value ) => {
545+ if ( typeof value === 'number' && value < 0 ) {
546+ control . setValue ( 0 , { emitEvent : false } ) ;
547+ }
548+ } ) ;
549+ }
550+ } ) ;
551+ const interestRateControl = this . loansAccountTermsForm . get ( 'interestRatePerPeriod' ) ;
552+ if ( interestRateControl ) {
553+ interestRateControl . valueChanges . subscribe ( ( value ) => {
554+ if ( typeof value === 'number' && value < 0.01 ) {
555+ interestRateControl . setValue ( 0.01 , { emitEvent : false } ) ;
556+ }
557+ } ) ;
558+ }
559+ }
560+
528561 setAdvancedPaymentStrategyControls ( ) : void {
529562 // Fixed Length validation
530563 if ( this . loansAccountTermsData ) {
@@ -533,7 +566,10 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
533566 if ( this . loansAccountTermsData . product . fixedLength ) {
534567 this . loansAccountTermsForm . addControl (
535568 'interestRatePerPeriod' ,
536- new UntypedFormControl ( { value : 0 , disabled : true } , Validators . required )
569+ new UntypedFormControl ( { value : 0 , disabled : true } , [
570+ Validators . required ,
571+ Validators . min ( 0.01 )
572+ ] )
537573 ) ;
538574 this . loansAccountTermsForm . addControl (
539575 'fixedLength' ,
@@ -542,7 +578,10 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
542578 } else {
543579 this . loansAccountTermsForm . addControl (
544580 'interestRatePerPeriod' ,
545- new UntypedFormControl ( this . loansAccountTermsData . interestRatePerPeriod , Validators . required )
581+ new UntypedFormControl ( this . loansAccountTermsData . interestRatePerPeriod , [
582+ Validators . required ,
583+ Validators . min ( 0.01 )
584+ ] )
546585 ) ;
547586 }
548587 }
@@ -569,19 +608,28 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
569608 ] ,
570609 loanTermFrequency : [
571610 { value : '' , disabled : true } ,
572- Validators . required
611+ [
612+ Validators . required ,
613+ Validators . min ( 0 )
614+ ]
573615 ] ,
574616 loanTermFrequencyType : [
575617 '' ,
576618 Validators . required
577619 ] ,
578620 numberOfRepayments : [
579621 '' ,
580- Validators . required
622+ [
623+ Validators . required ,
624+ Validators . min ( 0 )
625+ ]
581626 ] ,
582627 repaymentEvery : [
583628 '' ,
584- Validators . required
629+ [
630+ Validators . required ,
631+ Validators . min ( 0 )
632+ ]
585633 ] ,
586634 repaymentFrequencyType : [
587635 { value : '' , disabled : true } ,
@@ -591,7 +639,10 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
591639 repaymentFrequencyDayOfWeekType : [ '' ] ,
592640 repaymentsStartingFromDate : [ '' ] ,
593641 interestChargedFromDate : [ '' ] ,
594- interestRatePerPeriod : [ '' ] ,
642+ interestRatePerPeriod : [
643+ '' ,
644+ Validators . min ( 0.01 )
645+ ] ,
595646 interestType : [ '' ] ,
596647 isFloatingInterestRate : [ null ] ,
597648 isEqualAmortization : [ '' ] ,
@@ -601,11 +652,26 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
601652 ] ,
602653 interestCalculationPeriodType : [ '' ] ,
603654 allowPartialPeriodInterestCalculation : [ '' ] ,
604- inArrearsTolerance : [ '' ] ,
605- graceOnInterestCharged : [ '' ] ,
606- graceOnPrincipalPayment : [ '' ] ,
607- graceOnInterestPayment : [ '' ] ,
608- graceOnArrearsAgeing : [ '' ] ,
655+ inArrearsTolerance : [
656+ '' ,
657+ Validators . min ( 0 )
658+ ] ,
659+ graceOnInterestCharged : [
660+ '' ,
661+ Validators . min ( 0 )
662+ ] ,
663+ graceOnPrincipalPayment : [
664+ '' ,
665+ Validators . min ( 0 )
666+ ] ,
667+ graceOnInterestPayment : [
668+ '' ,
669+ Validators . min ( 0 )
670+ ] ,
671+ graceOnArrearsAgeing : [
672+ '' ,
673+ Validators . min ( 0 )
674+ ] ,
609675 loanIdToClose : [ '' ] ,
610676 fixedEmiAmount : [ '' ] ,
611677 isTopup : [ '' ] ,
@@ -689,7 +755,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
689755 * Adds the Disbursement Data entry form to given Disbursement Data entry.
690756 */
691757 addDisbursementDataEntry ( ) {
692- const currentPrincipalAmount = this . loansAccountTermsForm . get ( 'principalAmount' ) . value ;
758+ const currentPrincipalAmount = this . loansAccountTermsForm . get ( 'principalAmount' ) ? .value ;
693759 const formfields : FormfieldBase [ ] = [
694760 new DatepickerBase ( {
695761 controlName : 'expectedDisbursementDate' ,
@@ -734,7 +800,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
734800 * @param {number } index Array index from where Disbursement Data entry form needs to be removed.
735801 */
736802 removeDisbursementDataEntry ( index : number ) {
737- const currentPrincipalAmount = this . loansAccountTermsForm . get ( 'principalAmount' ) . value ;
803+ const currentPrincipalAmount = this . loansAccountTermsForm . get ( 'principalAmount' ) ? .value ;
738804 const dialogRef = this . dialog . open ( DeleteDialogComponent , {
739805 data : { deleteContext : `this` }
740806 } ) ;
@@ -814,7 +880,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp
814880 this . clientActiveLoanData = this . loansAccountProductTemplate . clientActiveLoanOptions ;
815881 this . loanScheduleType = this . loansAccountProductTemplate . loanScheduleType ;
816882 this . transactionProcessingStrategyOptions = [ ] ;
817- if ( this . loanScheduleType . code === LoanProducts . LOAN_SCHEDULE_TYPE_CUMULATIVE ) {
883+ if ( this . loanScheduleType ? .code === LoanProducts . LOAN_SCHEDULE_TYPE_CUMULATIVE ) {
818884 // Filter Advanced Payment Allocation Strategy
819885 this . transactionProcessingStrategyOptions =
820886 this . loansAccountProductTemplate . transactionProcessingStrategyOptions . filter (
0 commit comments