WEB-292: Backdated Interest modification (for progressive) on closed or overpaid loans
This commit is contained in:
@@ -30,6 +30,7 @@ Mifos X Web App is a modern single-page application (SPA) built on top of the Mi
|
|||||||
Before installing the web app, you need to set up the Fineract backend server:
|
Before installing the web app, you need to set up the Fineract backend server:
|
||||||
|
|
||||||
1. **Choose ONE of these backend options:**
|
1. **Choose ONE of these backend options:**
|
||||||
|
|
||||||
- **Option A: Use existing remote server**
|
- **Option A: Use existing remote server**
|
||||||
- Use the sandbox (MariaDB) at https://sandbox.mifos.community ** System is restored every 6 hours **
|
- Use the sandbox (MariaDB) at https://sandbox.mifos.community ** System is restored every 6 hours **
|
||||||
- Use the demo (MariaDB) at https://demo.mifos.community
|
- Use the demo (MariaDB) at https://demo.mifos.community
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ Also keep in mind this general rules:
|
|||||||
## Best practices
|
## Best practices
|
||||||
|
|
||||||
- Use object-oriented CSS (OOCSS):
|
- Use object-oriented CSS (OOCSS):
|
||||||
|
|
||||||
- Factorize common code in base class, and extend it, for example:
|
- Factorize common code in base class, and extend it, for example:
|
||||||
|
|
||||||
```scss
|
```scss
|
||||||
|
|||||||
@@ -11,14 +11,17 @@ This document provides step-by-step instructions for setting up test automation
|
|||||||
## Creating an Account on testRigor
|
## Creating an Account on testRigor
|
||||||
|
|
||||||
1. **Visit the testRigor website:**
|
1. **Visit the testRigor website:**
|
||||||
|
|
||||||
- Go to [testRigor](https://www.testrigor.com/).
|
- Go to [testRigor](https://www.testrigor.com/).
|
||||||
|
|
||||||
2. **Sign up for a new account:**
|
2. **Sign up for a new account:**
|
||||||
|
|
||||||
- Click on the "Sign Up" button on the top right corner.
|
- Click on the "Sign Up" button on the top right corner.
|
||||||
- Select the "Public Open Source" version.
|
- Select the "Public Open Source" version.
|
||||||
- Fill in the required details and follow the instructions to complete the registration.
|
- Fill in the required details and follow the instructions to complete the registration.
|
||||||
|
|
||||||
3. **Verify your email and log in:**
|
3. **Verify your email and log in:**
|
||||||
|
|
||||||
- Check your email inbox for a verification email from testRigor.
|
- Check your email inbox for a verification email from testRigor.
|
||||||
- Click on the verification link to activate your account.
|
- Click on the verification link to activate your account.
|
||||||
- Once your account is activated, log in.
|
- Once your account is activated, log in.
|
||||||
@@ -29,6 +32,7 @@ This document provides step-by-step instructions for setting up test automation
|
|||||||
## Running Tests with the CLI
|
## Running Tests with the CLI
|
||||||
|
|
||||||
1. **Install testRigor CLI:**
|
1. **Install testRigor CLI:**
|
||||||
|
|
||||||
- Ensure you have Node.js installed on your machine (version 18 or higher).
|
- Ensure you have Node.js installed on your machine (version 18 or higher).
|
||||||
- Install the testRigor CLI globally using npm:
|
- Install the testRigor CLI globally using npm:
|
||||||
```bash
|
```bash
|
||||||
@@ -36,10 +40,12 @@ This document provides step-by-step instructions for setting up test automation
|
|||||||
```
|
```
|
||||||
|
|
||||||
2. **Obtain Required Parameters:**
|
2. **Obtain Required Parameters:**
|
||||||
|
|
||||||
- **Test Suite ID:** You can obtain the Test Suite ID in the URL of your test suite. If the URL is `https://app.testrigor.com/test-suites/12345`, then `12345` is your Test Suite ID.
|
- **Test Suite ID:** You can obtain the Test Suite ID in the URL of your test suite. If the URL is `https://app.testrigor.com/test-suites/12345`, then `12345` is your Test Suite ID.
|
||||||
- **Auth Token:** You can obtain your token from the "CI/CD integration" section on testRigor. Look for "auth-token" and copy the value next to it, which will be in the format `########-####-####-####-############`.
|
- **Auth Token:** You can obtain your token from the "CI/CD integration" section on testRigor. Look for "auth-token" and copy the value next to it, which will be in the format `########-####-####-####-############`.
|
||||||
|
|
||||||
3. **Set Parameters in `run_testrigor_tests.sh`:**
|
3. **Set Parameters in `run_testrigor_tests.sh`:**
|
||||||
|
|
||||||
- Before running the tests, create a .env file on the testRigor directory and set the following variables to the parameters you obtained:
|
- Before running the tests, create a .env file on the testRigor directory and set the following variables to the parameters you obtained:
|
||||||
- `MIFOS_TEST_SUITE_ID`: Set this variable to your Test Suite ID.
|
- `MIFOS_TEST_SUITE_ID`: Set this variable to your Test Suite ID.
|
||||||
- `MIFOS_AUTH_TOKEN`: Set this variable to your auth token.
|
- `MIFOS_AUTH_TOKEN`: Set this variable to your auth token.
|
||||||
|
|||||||
+4
-6
@@ -1,7 +1,7 @@
|
|||||||
/** Angular Imports. */
|
/** Angular Imports. */
|
||||||
import { Component, OnInit, Input } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, FormControl, ReactiveFormsModule } from '@angular/forms';
|
import { UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Dates } from 'app/core/utils/dates';
|
import { Dates } from 'app/core/utils/dates';
|
||||||
|
|
||||||
/** Custom Services. */
|
/** Custom Services. */
|
||||||
@@ -12,7 +12,6 @@ import { InputAmountComponent } from '../../../../shared/input-amount/input-amou
|
|||||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Approve Loan component.
|
* Approve Loan component.
|
||||||
@@ -25,8 +24,7 @@ import { MatIcon } from '@angular/material/icon';
|
|||||||
...STANDALONE_SHARED_IMPORTS,
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
InputAmountComponent,
|
InputAmountComponent,
|
||||||
CdkTextareaAutosize,
|
CdkTextareaAutosize,
|
||||||
FormatNumberPipe,
|
FormatNumberPipe
|
||||||
MatIcon
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ApproveLoanComponent implements OnInit {
|
export class ApproveLoanComponent implements OnInit {
|
||||||
|
|||||||
+3
-11
@@ -1,12 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import {
|
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||||
UntypedFormBuilder,
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
UntypedFormControl,
|
|
||||||
UntypedFormGroup,
|
|
||||||
Validators,
|
|
||||||
ReactiveFormsModule
|
|
||||||
} from '@angular/forms';
|
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
|
||||||
import { Dates } from 'app/core/utils/dates';
|
import { Dates } from 'app/core/utils/dates';
|
||||||
import { LoansService } from 'app/loans/loans.service';
|
import { LoansService } from 'app/loans/loans.service';
|
||||||
import { SettingsService } from 'app/settings/settings.service';
|
import { SettingsService } from 'app/settings/settings.service';
|
||||||
@@ -15,7 +9,6 @@ import { InputAmountComponent } from '../../../../shared/input-amount/input-amou
|
|||||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'mifosx-disburse-to-savings-account',
|
selector: 'mifosx-disburse-to-savings-account',
|
||||||
@@ -25,8 +18,7 @@ import { MatIcon } from '@angular/material/icon';
|
|||||||
...STANDALONE_SHARED_IMPORTS,
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
InputAmountComponent,
|
InputAmountComponent,
|
||||||
CdkTextareaAutosize,
|
CdkTextareaAutosize,
|
||||||
FormatNumberPipe,
|
FormatNumberPipe
|
||||||
MatIcon
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class DisburseToSavingsAccountComponent implements OnInit {
|
export class DisburseToSavingsAccountComponent implements OnInit {
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
/** Angular Imports */
|
/** Angular Imports */
|
||||||
import { Component, OnInit, Input } from '@angular/core';
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
import {
|
import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms';
|
||||||
UntypedFormGroup,
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
UntypedFormBuilder,
|
|
||||||
Validators,
|
|
||||||
UntypedFormControl,
|
|
||||||
ReactiveFormsModule
|
|
||||||
} from '@angular/forms';
|
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
|
||||||
|
|
||||||
/** Custom Services */
|
/** Custom Services */
|
||||||
import { LoansService } from 'app/loans/loans.service';
|
import { LoansService } from 'app/loans/loans.service';
|
||||||
@@ -19,7 +13,6 @@ import { MatSlideToggle } from '@angular/material/slide-toggle';
|
|||||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disburse Loan Option
|
* Disburse Loan Option
|
||||||
@@ -33,8 +26,7 @@ import { MatIcon } from '@angular/material/icon';
|
|||||||
InputAmountComponent,
|
InputAmountComponent,
|
||||||
MatSlideToggle,
|
MatSlideToggle,
|
||||||
CdkTextareaAutosize,
|
CdkTextareaAutosize,
|
||||||
FormatNumberPipe,
|
FormatNumberPipe
|
||||||
MatIcon
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class DisburseComponent implements OnInit {
|
export class DisburseComponent implements OnInit {
|
||||||
|
|||||||
@@ -307,7 +307,9 @@
|
|||||||
{{ 'labels.inputs.Charges' | translate }}
|
{{ 'labels.inputs.Charges' | translate }}
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="loanDetailsData.status.active">
|
<ng-container
|
||||||
|
*ngIf="loanDetailsData.status.active || loanDetailsData.status.closed || loanDetailsData.status.overpaid"
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
mat-tab-link
|
mat-tab-link
|
||||||
[routerLink]="['./loan-reschedules']"
|
[routerLink]="['./loan-reschedules']"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/** Angular Imports */
|
/** Angular Imports */
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, NavigationExtras, Router, RouterLinkActive, RouterLink, RouterOutlet } from '@angular/router';
|
import { ActivatedRoute, NavigationExtras, Router, RouterLinkActive, RouterOutlet } from '@angular/router';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
/** Custom Services */
|
/** Custom Services */
|
||||||
@@ -18,10 +18,10 @@ import { DelinquencyPausePeriod } from '../models/loan-account.model';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { LoanTransaction } from 'app/products/loan-products/models/loan-account.model';
|
import { LoanTransaction } from 'app/products/loan-products/models/loan-account.model';
|
||||||
import { OptionData } from 'app/shared/models/option-data.model';
|
import { OptionData } from 'app/shared/models/option-data.model';
|
||||||
import { MatCard, MatCardHeader, MatCardTitleGroup, MatCardTitle, MatCardContent } from '@angular/material/card';
|
import { MatCardHeader, MatCardTitleGroup, MatCardTitle } from '@angular/material/card';
|
||||||
import { SvgIconComponent } from '../../shared/svg-icon/svg-icon.component';
|
import { SvgIconComponent } from '../../shared/svg-icon/svg-icon.component';
|
||||||
import { MatTooltip } from '@angular/material/tooltip';
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
import { NgClass, NgIf, NgFor, CurrencyPipe } from '@angular/common';
|
import { NgClass, CurrencyPipe } from '@angular/common';
|
||||||
import { LongTextComponent } from '../../shared/long-text/long-text.component';
|
import { LongTextComponent } from '../../shared/long-text/long-text.component';
|
||||||
import { AccountNumberComponent } from '../../shared/account-number/account-number.component';
|
import { AccountNumberComponent } from '../../shared/account-number/account-number.component';
|
||||||
import { MatIconButton } from '@angular/material/button';
|
import { MatIconButton } from '@angular/material/button';
|
||||||
@@ -33,6 +33,7 @@ import { StatusLookupPipe } from '../../pipes/status-lookup.pipe';
|
|||||||
import { DateFormatPipe } from '../../pipes/date-format.pipe';
|
import { DateFormatPipe } from '../../pipes/date-format.pipe';
|
||||||
import { FormatNumberPipe } from '../../pipes/format-number.pipe';
|
import { FormatNumberPipe } from '../../pipes/format-number.pipe';
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
|
import { LoanProducts } from 'app/products/loan-products/loan-products';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'mifosx-loans-view',
|
selector: 'mifosx-loans-view',
|
||||||
@@ -295,6 +296,13 @@ export class LoansViewComponent implements OnInit {
|
|||||||
taskPermissionName: 'DISBURSE_LOAN'
|
taskPermissionName: 'DISBURSE_LOAN'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (LoanProducts.isAdvancedPaymentAllocationStrategy(this.loanDetailsData.transactionProcessingStrategyCode)) {
|
||||||
|
this.buttonConfig.addButton({
|
||||||
|
name: 'Reschedule',
|
||||||
|
icon: 'calendar',
|
||||||
|
taskPermissionName: 'CREATE_RESCHEDULELOAN'
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user