Remark Loan product attributes that uses default values from global configurations (#1783)
Co-authored-by: Jose Alberto Hernandez <alberto@blue-daemon.local>
This commit is contained in:
co-authored by
Jose Alberto Hernandez
parent
9f2c644877
commit
e1e3429b66
@@ -11,7 +11,6 @@ import { AuthenticationService } from './authentication/authentication.service';
|
|||||||
import { HttpService } from './http/http.service';
|
import { HttpService } from './http/http.service';
|
||||||
import { HttpCacheService } from './http/http-cache.service';
|
import { HttpCacheService } from './http/http-cache.service';
|
||||||
import { ProgressBarService } from './progress-bar/progress-bar.service';
|
import { ProgressBarService } from './progress-bar/progress-bar.service';
|
||||||
import { I18nService } from './i18n/i18n.service';
|
|
||||||
|
|
||||||
/** Custom Guards */
|
/** Custom Guards */
|
||||||
import { AuthenticationGuard } from './authentication/authentication.guard';
|
import { AuthenticationGuard } from './authentication/authentication.guard';
|
||||||
@@ -68,7 +67,6 @@ import { ContentComponent } from './shell/content/content.component';
|
|||||||
useClass: AuthenticationInterceptor,
|
useClass: AuthenticationInterceptor,
|
||||||
multi: true
|
multi: true
|
||||||
},
|
},
|
||||||
I18nService,
|
|
||||||
HttpCacheService,
|
HttpCacheService,
|
||||||
ApiPrefixInterceptor,
|
ApiPrefixInterceptor,
|
||||||
ErrorHandlerInterceptor,
|
ErrorHandlerInterceptor,
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
// import { TestBed, inject } from '@angular/core/testing';
|
|
||||||
|
|
||||||
// import { TranslateService, LangChangeEvent } from '@ngx-translate/core';
|
|
||||||
// import { Subject } from 'rxjs';
|
|
||||||
|
|
||||||
// import { extract, I18nService } from './i18n.service';
|
|
||||||
|
|
||||||
// const defaultLanguage = 'en-US';
|
|
||||||
// const supportedLanguages = ['eo', 'en-US', 'fr-FR'];
|
|
||||||
|
|
||||||
// class MockTranslateService {
|
|
||||||
|
|
||||||
// currentLang: string;
|
|
||||||
// onLangChange = new Subject();
|
|
||||||
|
|
||||||
// use(language: string) {
|
|
||||||
// this.currentLang = language;
|
|
||||||
// this.onLangChange.next({
|
|
||||||
// lang: this.currentLang,
|
|
||||||
// translations: {}
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// getBrowserCultureLang() {
|
|
||||||
// return 'en-US';
|
|
||||||
// }
|
|
||||||
|
|
||||||
// setTranslation(lang: string, translations: Object, shouldMerge?: boolean) { }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// describe('I18nService', () => {
|
|
||||||
// let i18nService: I18nService;
|
|
||||||
// let translateService: TranslateService;
|
|
||||||
// let onLangChangeSpy: jasmine.Spy;
|
|
||||||
|
|
||||||
// beforeEach(() => {
|
|
||||||
// TestBed.configureTestingModule({
|
|
||||||
// providers: [
|
|
||||||
// I18nService,
|
|
||||||
// { provide: TranslateService, useClass: MockTranslateService },
|
|
||||||
// ]
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// beforeEach(inject([
|
|
||||||
// I18nService,
|
|
||||||
// TranslateService
|
|
||||||
// ], (_i18nService: I18nService,
|
|
||||||
// _translateService: TranslateService) => {
|
|
||||||
|
|
||||||
// i18nService = _i18nService;
|
|
||||||
// translateService = _translateService;
|
|
||||||
|
|
||||||
// // Create spies
|
|
||||||
// onLangChangeSpy = jasmine.createSpy('onLangChangeSpy');
|
|
||||||
// translateService.onLangChange
|
|
||||||
// .subscribe((event: LangChangeEvent) => {
|
|
||||||
// onLangChangeSpy(event.lang);
|
|
||||||
// });
|
|
||||||
// spyOn(translateService, 'use').and.callThrough();
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// afterEach(() => {
|
|
||||||
// // Cleanup
|
|
||||||
// localStorage.removeItem('language');
|
|
||||||
// });
|
|
||||||
|
|
||||||
// describe('extract', () => {
|
|
||||||
// it('should not modify string', () => {
|
|
||||||
// expect(extract('Hello world !')).toEqual('Hello world !');
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// describe('init', () => {
|
|
||||||
// it('should init with default language', () => {
|
|
||||||
// // Act
|
|
||||||
// i18nService.init(defaultLanguage, supportedLanguages);
|
|
||||||
|
|
||||||
// // Assert
|
|
||||||
// expect(translateService.use).toHaveBeenCalledWith(defaultLanguage);
|
|
||||||
// expect(onLangChangeSpy).toHaveBeenCalledWith(defaultLanguage);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should init with save language', () => {
|
|
||||||
// // Arrange
|
|
||||||
// const savedLanguage = 'eo';
|
|
||||||
// localStorage.setItem('language', savedLanguage);
|
|
||||||
|
|
||||||
// // Act
|
|
||||||
// i18nService.init(defaultLanguage, supportedLanguages);
|
|
||||||
|
|
||||||
// // Assert
|
|
||||||
// expect(translateService.use).toHaveBeenCalledWith(savedLanguage);
|
|
||||||
// expect(onLangChangeSpy).toHaveBeenCalledWith(savedLanguage);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// describe('set language', () => {
|
|
||||||
// it('should change current language', () => {
|
|
||||||
// // Arrange
|
|
||||||
// const newLanguage = 'eo';
|
|
||||||
// i18nService.init(defaultLanguage, supportedLanguages);
|
|
||||||
|
|
||||||
// // Act
|
|
||||||
// i18nService.language = newLanguage;
|
|
||||||
|
|
||||||
// // Assert
|
|
||||||
// expect(translateService.use).toHaveBeenCalledWith(newLanguage);
|
|
||||||
// expect(onLangChangeSpy).toHaveBeenCalledWith(newLanguage);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should change current language without a region match', () => {
|
|
||||||
// // Arrange
|
|
||||||
// const newLanguage = 'fr-CA';
|
|
||||||
// i18nService.init(defaultLanguage, supportedLanguages);
|
|
||||||
|
|
||||||
// // Act
|
|
||||||
// i18nService.language = newLanguage;
|
|
||||||
|
|
||||||
// // Assert
|
|
||||||
// expect(translateService.use).toHaveBeenCalledWith('fr-FR');
|
|
||||||
// expect(onLangChangeSpy).toHaveBeenCalledWith('fr-FR');
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should change current language to default if unsupported', () => {
|
|
||||||
// // Arrange
|
|
||||||
// const newLanguage = 'es';
|
|
||||||
// i18nService.init(defaultLanguage, supportedLanguages);
|
|
||||||
|
|
||||||
// // Act
|
|
||||||
// i18nService.language = newLanguage;
|
|
||||||
|
|
||||||
// // Assert
|
|
||||||
// expect(translateService.use).toHaveBeenCalledWith(defaultLanguage);
|
|
||||||
// expect(onLangChangeSpy).toHaveBeenCalledWith(defaultLanguage);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// describe('get language', () => {
|
|
||||||
// it('should return current language', () => {
|
|
||||||
// // Arrange
|
|
||||||
// i18nService.init(defaultLanguage, supportedLanguages);
|
|
||||||
|
|
||||||
// // Act
|
|
||||||
// const currentLanguage = i18nService.language;
|
|
||||||
|
|
||||||
// // Assert
|
|
||||||
// expect(currentLanguage).toEqual(defaultLanguage);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// });
|
|
||||||
@@ -1,2 +1,9 @@
|
|||||||
mifosx-content { min-height: 100%; height: auto !important; height: 100%; margin: 0 auto -30px; }
|
mifosx-content {
|
||||||
#push { height:30px;}
|
min-height: 100%;
|
||||||
|
height: auto !important;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 auto -30px;
|
||||||
|
}
|
||||||
|
#push {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,12 +48,16 @@ export class CreateLoanProductComponent implements OnInit {
|
|||||||
const assetAccountData = this.loanProductsTemplate.accountingMappingOptions.assetAccountOptions || [];
|
const assetAccountData = this.loanProductsTemplate.accountingMappingOptions.assetAccountOptions || [];
|
||||||
const liabilityAccountData = this.loanProductsTemplate.accountingMappingOptions.liabilityAccountOptions || [];
|
const liabilityAccountData = this.loanProductsTemplate.accountingMappingOptions.liabilityAccountOptions || [];
|
||||||
this.loanProductsTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions = assetAccountData.concat(liabilityAccountData);
|
this.loanProductsTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions = assetAccountData.concat(liabilityAccountData);
|
||||||
|
const itemsByDefault: string[] = [];
|
||||||
data.configurations.globalConfiguration.forEach((config: GlobalConfiguration) => {
|
data.configurations.globalConfiguration.forEach((config: GlobalConfiguration) => {
|
||||||
if (config.name === 'days-before-repayment-is-due') {
|
if (config.name === 'days-before-repayment-is-due') {
|
||||||
this.loanProductsTemplate['dueDaysForRepaymentEvent'] = config.value;
|
this.loanProductsTemplate['dueDaysForRepaymentEvent'] = config.value;
|
||||||
|
itemsByDefault.push('dueDaysForRepaymentEvent');
|
||||||
} else if (config.name === 'days-after-repayment-is-overdue') {
|
} else if (config.name === 'days-after-repayment-is-overdue') {
|
||||||
this.loanProductsTemplate['overDueDaysForRepaymentEvent'] = config.value;
|
this.loanProductsTemplate['overDueDaysForRepaymentEvent'] = config.value;
|
||||||
|
itemsByDefault.push('overDueDaysForRepaymentEvent');
|
||||||
}
|
}
|
||||||
|
this.loanProductsTemplate['itemsByDefault'] = itemsByDefault;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,16 +48,20 @@ export class EditLoanProductComponent implements OnInit {
|
|||||||
const assetAccountData = this.loanProductAndTemplate.accountingMappingOptions.assetAccountOptions || [];
|
const assetAccountData = this.loanProductAndTemplate.accountingMappingOptions.assetAccountOptions || [];
|
||||||
const liabilityAccountData = this.loanProductAndTemplate.accountingMappingOptions.liabilityAccountOptions || [];
|
const liabilityAccountData = this.loanProductAndTemplate.accountingMappingOptions.liabilityAccountOptions || [];
|
||||||
this.loanProductAndTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions = assetAccountData.concat(liabilityAccountData);
|
this.loanProductAndTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions = assetAccountData.concat(liabilityAccountData);
|
||||||
|
const itemsByDefault: string[] = [];
|
||||||
data.configurations.globalConfiguration.forEach((config: GlobalConfiguration) => {
|
data.configurations.globalConfiguration.forEach((config: GlobalConfiguration) => {
|
||||||
if (config.name === 'days-before-repayment-is-due') {
|
if (config.name === 'days-before-repayment-is-due') {
|
||||||
if (this.loanProductAndTemplate['dueDaysForRepaymentEvent'] == null) {
|
if (this.loanProductAndTemplate['dueDaysForRepaymentEvent'] == null) {
|
||||||
this.loanProductAndTemplate['dueDaysForRepaymentEvent'] = config.value;
|
this.loanProductAndTemplate['dueDaysForRepaymentEvent'] = config.value;
|
||||||
|
itemsByDefault.push('dueDaysForRepaymentEvent');
|
||||||
}
|
}
|
||||||
} else if (config.name === 'days-after-repayment-is-overdue') {
|
} else if (config.name === 'days-after-repayment-is-overdue') {
|
||||||
if (this.loanProductAndTemplate['overDueDaysForRepaymentEvent'] == null) {
|
if (this.loanProductAndTemplate['overDueDaysForRepaymentEvent'] == null) {
|
||||||
this.loanProductAndTemplate['overDueDaysForRepaymentEvent'] = config.value;
|
this.loanProductAndTemplate['overDueDaysForRepaymentEvent'] = config.value;
|
||||||
|
itemsByDefault.push('overDueDaysForRepaymentEvent');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.loanProductAndTemplate['itemsByDefault'] = itemsByDefault;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -416,16 +416,17 @@
|
|||||||
|
|
||||||
<mat-divider fxFlex="98%"></mat-divider>
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
<h3 fxFlex="23%" class="mat-h3">Event Settings</h3>
|
<h3 fxFlex="23%" class="mat-h3">Event Settings <i class="fas fa-question"
|
||||||
|
matTooltip="Setting for event notifications to be sent before or after repayments. Blue color means default value from global configurations."></i></h3>
|
||||||
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
<mat-form-field fxFlex="48%">
|
<mat-form-field fxFlex="48%">
|
||||||
<mat-label>Due days for repayment event</mat-label>
|
<mat-label [ngClass]="styleByDefault('dueDaysForRepaymentEvent')">Due days for repayment event</mat-label>
|
||||||
<input type="number" matInput matTooltip="Specific days before when repayment due notification should be sent." formControlName="dueDaysForRepaymentEvent" [min]="0">
|
<input type="number" matInput matTooltip="Specific days before when repayment due notification should be sent." formControlName="dueDaysForRepaymentEvent" [min]="0">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field fxFlex="48%">
|
<mat-form-field fxFlex="48%">
|
||||||
<mat-label>OverDue days for repayment event</mat-label>
|
<mat-label [ngClass]="styleByDefault('dueDaysForRepaymentEvent')">OverDue days for repayment event</mat-label>
|
||||||
<input type="number" matInput matTooltip="Specific days when after the repayment Overdue notification should be sent." formControlName="overDueDaysForRepaymentEvent" [min]="0">
|
<input type="number" matInput matTooltip="Specific days when after the repayment Overdue notification should be sent." formControlName="overDueDaysForRepaymentEvent" [min]="0">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+6
@@ -1,3 +1,5 @@
|
|||||||
|
@import "assets/styles/colours";
|
||||||
|
|
||||||
h3, h4 {
|
h3, h4 {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
@@ -21,3 +23,7 @@ mat-divider {
|
|||||||
.margin-t {
|
.margin-t {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.by-default {
|
||||||
|
color: $status-approved;
|
||||||
|
}
|
||||||
|
|||||||
+12
-2
@@ -28,6 +28,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
interestRecalculationOnDayTypeData: any;
|
interestRecalculationOnDayTypeData: any;
|
||||||
delinquencyBucketData: any;
|
delinquencyBucketData: any;
|
||||||
|
|
||||||
|
itemsByDefault: string[] = [];
|
||||||
|
|
||||||
constructor(private formBuilder: FormBuilder) {
|
constructor(private formBuilder: FormBuilder) {
|
||||||
this.createLoanProductSettingsForm();
|
this.createLoanProductSettingsForm();
|
||||||
this.setConditionalControls();
|
this.setConditionalControls();
|
||||||
@@ -58,6 +60,7 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
this.interestRecalculationOnDayTypeData = Array.from({ length: 28 }, (_, index) => index + 1);
|
this.interestRecalculationOnDayTypeData = Array.from({ length: 28 }, (_, index) => index + 1);
|
||||||
this.delinquencyBucketData = this.loanProductsTemplate.delinquencyBucketOptions;
|
this.delinquencyBucketData = this.loanProductsTemplate.delinquencyBucketOptions;
|
||||||
|
|
||||||
|
this.itemsByDefault = this.loanProductsTemplate.itemsByDefault || [];
|
||||||
this.loanProductSettingsForm.patchValue({
|
this.loanProductSettingsForm.patchValue({
|
||||||
'amortizationType': this.loanProductsTemplate.amortizationType.id,
|
'amortizationType': this.loanProductsTemplate.amortizationType.id,
|
||||||
'interestType': this.loanProductsTemplate.interestType.id,
|
'interestType': this.loanProductsTemplate.interestType.id,
|
||||||
@@ -88,7 +91,7 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
'outstandingLoanBalance': this.loanProductsTemplate.outstandingLoanBalance,
|
'outstandingLoanBalance': this.loanProductsTemplate.outstandingLoanBalance,
|
||||||
'dueDaysForRepaymentEvent': this.loanProductsTemplate.dueDaysForRepaymentEvent,
|
'dueDaysForRepaymentEvent': this.loanProductsTemplate.dueDaysForRepaymentEvent,
|
||||||
'overDueDaysForRepaymentEvent': this.loanProductsTemplate.overDueDaysForRepaymentEvent
|
'overDueDaysForRepaymentEvent': this.loanProductsTemplate.overDueDaysForRepaymentEvent
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.loanProductsTemplate.delinquencyBucket) {
|
if (this.loanProductsTemplate.delinquencyBucket) {
|
||||||
this.loanProductSettingsForm.patchValue({
|
this.loanProductSettingsForm.patchValue({
|
||||||
@@ -195,7 +198,7 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
this.loanProductSettingsForm.get('interestCalculationPeriodType').valueChanges
|
this.loanProductSettingsForm.get('interestCalculationPeriodType').valueChanges
|
||||||
.subscribe((interestCalculationPeriodType: any) => {
|
.subscribe((interestCalculationPeriodType: any) => {
|
||||||
if (interestCalculationPeriodType === 0) {
|
if (interestCalculationPeriodType === 0) {
|
||||||
this.loanProductSettingsForm.patchValue({'allowPartialPeriodInterestCalcualtion': false});
|
this.loanProductSettingsForm.patchValue({ 'allowPartialPeriodInterestCalcualtion': false });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -358,6 +361,13 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
styleByDefault(input: string): string {
|
||||||
|
if (this.itemsByDefault.includes(input)) {
|
||||||
|
return 'by-default';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
get loanProductSettings() {
|
get loanProductSettings() {
|
||||||
return this.loanProductSettingsForm.value;
|
return this.loanProductSettingsForm.value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ export class LanguageSelectorComponent implements OnInit {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the language of the application in the selector on initial setup.
|
* Sets the language of the application in the selector on initial setup.
|
||||||
* @param {I18nService} i18nService Internationalization Service.
|
* @param {TranslateService} translateService Translate Service.
|
||||||
*/
|
*/
|
||||||
constructor(private translate: TranslateService,
|
constructor(private translateService: TranslateService,
|
||||||
private settingsService: SettingsService) {
|
private settingsService: SettingsService) {
|
||||||
this.languageSelector.setValue(this.currentLanguage);
|
this.languageSelector.setValue(this.currentLanguage);
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ export class LanguageSelectorComponent implements OnInit {
|
|||||||
* @param {string} language New language.
|
* @param {string} language New language.
|
||||||
*/
|
*/
|
||||||
setLanguage() {
|
setLanguage() {
|
||||||
this.translate.use(this.languageSelector.value);
|
this.translateService.use(this.languageSelector.value);
|
||||||
this.settingsService.setLanguage({ name: '', code: this.languageSelector.value.substring(0, 2) });
|
this.settingsService.setLanguage({ name: '', code: this.languageSelector.value.substring(0, 2) });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ export class LanguageSelectorComponent implements OnInit {
|
|||||||
* @returns {string} Current language.
|
* @returns {string} Current language.
|
||||||
*/
|
*/
|
||||||
get currentLanguage(): string {
|
get currentLanguage(): string {
|
||||||
return this.translate.currentLang;
|
return this.translateService.currentLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +56,7 @@ export class LanguageSelectorComponent implements OnInit {
|
|||||||
* @return {string[]} Supported languages.
|
* @return {string[]} Supported languages.
|
||||||
*/
|
*/
|
||||||
get languages(): string[] {
|
get languages(): string[] {
|
||||||
return this.translate.getLangs();
|
return this.translateService.getLangs();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ export class WebAppComponent implements OnInit {
|
|||||||
* @param {ActivatedRoute} activatedRoute Activated Route.
|
* @param {ActivatedRoute} activatedRoute Activated Route.
|
||||||
* @param {Title} titleService Title Service.
|
* @param {Title} titleService Title Service.
|
||||||
* @param {TranslateService} translateService Translate Service.
|
* @param {TranslateService} translateService Translate Service.
|
||||||
* @param {I18nService} i18nService I18n Service.
|
|
||||||
* @param {ThemeStorageService} themeStorageService Theme Storage Service.
|
* @param {ThemeStorageService} themeStorageService Theme Storage Service.
|
||||||
* @param {MatSnackBar} snackBar Material Snackbar for notifications.
|
* @param {MatSnackBar} snackBar Material Snackbar for notifications.
|
||||||
* @param {AlertService} alertService Alert Service.
|
* @param {AlertService} alertService Alert Service.
|
||||||
|
|||||||
Reference in New Issue
Block a user