Merging all changes in main branch of the last weeks into dev branch (#2444)

* fixed identities tab

* fix: Loan Product capitalized income form validation

* Loan account with Capitalized Income transaction

* fix: Use first API url from url list

* Loan Product with Capitalized Income GL accounting mappings

* fix: Loan Product capitalized income with Income Type

* Loan account details - income capitalization type

* fix: Loan Product Cash accounting view

* fix: Loan Id updated in Loan views after url changed

* fix: Charge management minimum and maximum cap values validation

* build(deps-dev): bump http-proxy-middleware from 2.0.7 to 2.0.9 (#2421)

Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.7 to 2.0.9.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.9/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.7...v2.0.9)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-version: 2.0.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: Improve contributing guidelines (#2440)

The CONTRIBUTING.md file has been updated to clarify that
we use the dev branch for development. In addition to
that, I have slightly shortened and restructured the text.

FIXES: WEB-165

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Craig-Rosario <craig.rosario04@gmail.com>
Co-authored-by: Jose Alberto Hernandez <alberto@art3ch.solutions>
Co-authored-by: Jose Alberto Hernandez <alberto@black-box.local>
Co-authored-by: adam.magyari <magyari.adam96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Felix van Hove
2025-05-05 10:36:01 -06:00
committed by GitHub
co-authored by Craig-Rosario Jose Alberto Hernandez Jose Alberto Hernandez adam.magyari dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
parent b61d9e3d34
commit c8d857f3cb
60 changed files with 560 additions and 266 deletions
@@ -92,7 +92,6 @@ export class GlAccountTreeService {
// and rest as children to respective parent nodes.
for (const glAccount of glAccountData) {
if (glAccount.parentId === 0) {
console.log(glAccount.type.value);
if (glAccount.type.value === 'ASSET') {
glAccountTree[0].children[0].children.push(glAccounts[glAccount.id]);
} else if (glAccount.type.value === 'EQUITY') {
@@ -46,7 +46,6 @@ export class EditFinancialActivityMappingComponent implements OnInit {
) {
this.route.data.subscribe((data: { financialActivityAccountAndTemplate: any }) => {
this.financialActivityAccountId = data.financialActivityAccountAndTemplate.id;
console.log(data.financialActivityAccountAndTemplate.financialActivityData);
this.financialActivityId = data.financialActivityAccountAndTemplate.financialActivityData.id;
this.glAccountId = data.financialActivityAccountAndTemplate.glAccountData.id;
this.glAccountOptions = data.financialActivityAccountAndTemplate.glAccountOptions;
@@ -1,17 +1,21 @@
<div class="tab-container mat-typography">
<h3>{{ 'labels.heading.Identities' | translate }}</h3>
<div class="header-row" fxLayout="row" fxLayoutAlign="space-between">
<h3 class="mat-subheading-2">
{{ 'labels.heading.Identities' | translate }}
</h3>
<button
mat-raised-button
class="f-right"
color="primary"
(click)="addIdentifier()"
*mifosxHasPermission="'CREATE_CLIENTIDENTIFIER'"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon> {{ 'labels.buttons.Add' | translate }}
</button>
<button
mat-raised-button
color="primary"
(click)="addIdentifier()"
*mifosxHasPermission="'CREATE_CLIENTIDENTIFIER'"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table mat-table #identifiersTable [dataSource]="clientIdentities">
<table mat-table #identifiersTable [dataSource]="clientIdentities" [ngStyle]="{ 'margin-top': '3%' }">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Id' | translate }}</th>
<td mat-cell *matCellDef="let identity">{{ identity.id }}</td>
@@ -3,7 +3,7 @@
margin: 1%;
h3 {
margin: 1% auto;
margin: 0;
}
table {
+1 -1
View File
@@ -41,7 +41,7 @@ export class Accounting {
'ACCRUAL (UPFRONT)'
].includes(value)) {
return 'Accrual (upfront)';
} else if (value === 'CASH BASED') {
} else if (value.startsWith('CASH')) {
return 'Cash';
} else if (value === 'NONE') {
return 'NONE';
@@ -68,7 +68,6 @@ export class FixedDepositAccountTermsStepComponent implements OnInit, OnChanges
depositPeriod: this.fixedDepositsAccountTemplate.depositPeriod,
depositPeriodFrequencyId: this.fixedDepositsAccountTemplate.depositPeriodFrequency.id
});
console.log(this.fixedDepositAccountTermsForm.value);
}
}
@@ -31,8 +31,7 @@ export class LoanActionButtonResolver implements Resolve<Object> {
return this.loansService.getLoanActionTemplate(loanId, 'repayment');
} else if (loanActionButton === 'Goodwill Credit') {
return this.loansService.getLoanActionTemplate(loanId, 'goodwillCredit');
}
if (loanActionButton === 'Interest Payment Waiver') {
} else if (loanActionButton === 'Interest Payment Waiver') {
return this.loansService.getLoanActionTemplate(loanId, 'interestPaymentWaiver');
} else if (loanActionButton === 'Payout Refund') {
return this.loansService.getLoanActionTemplate(loanId, 'payoutRefund');
@@ -74,6 +73,8 @@ export class LoanActionButtonResolver implements Resolve<Object> {
return this.loansService.getLoanForeclosureActionTemplate(loanId);
} else if (loanActionButton === 'Charge-Off') {
return this.loansService.getLoanActionTemplate(loanId, 'charge-off');
} else if (loanActionButton === 'Capitalized Income') {
return this.loansService.getLoanActionTemplate(loanId, 'capitalizedIncome');
} else {
return undefined;
}
@@ -94,6 +94,11 @@
<span fxFlex="50%"> {{ loanDetails.capitalizedIncomeStrategy?.value | translateKey: 'catalogs' }} </span>
</div>
<div fxFlexFill *ngIf="loanDetails.enableIncomeCapitalization">
<span fxFlex="50%"> {{ 'labels.inputs.Income capitalization type' | translate }}</span>
<span fxFlex="50%"> {{ loanDetails.capitalizedIncomeType?.value | translateKey: 'catalogs' }} </span>
</div>
<div fxFlexFill>
<span fxFlex="50%"> {{ 'labels.inputs.Grace: On Principal Payment' | translate }}</span>
<span fxFlex="50%"> {{ loanDetails.graceOnPrincipalPayment }} </span>
@@ -6,7 +6,7 @@ import { ActivatedRoute } from '@angular/router';
templateUrl: './datatable-tab.component.html',
styleUrls: ['./datatable-tab.component.scss']
})
export class DatatableTabComponent {
export class DatatableTabComponent implements OnInit {
entityId: string;
/** Loan Datatable */
entityDatatable: any = null;
@@ -25,4 +25,10 @@ export class DatatableTabComponent {
this.multiRowDatatableFlag = this.entityDatatable.columnHeaders[0].columnName === 'id' ? true : false;
});
}
ngOnInit() {
this.route.parent.parent.params.subscribe((params) => {
this.entityId = params['loanId'];
});
}
}
@@ -7,6 +7,7 @@
<mifosx-foreclosure [dataObject]="actionButtonData" *ngIf="actions['Foreclosure']"></mifosx-foreclosure>
<mifosx-prepay-loan [dataObject]="actionButtonData" *ngIf="actions['Prepay Loan']"></mifosx-prepay-loan>
<mifosx-make-repayment [dataObject]="actionButtonData" *ngIf="actions['Make Repayment']"></mifosx-make-repayment>
<mifosx-make-repayment [dataObject]="actionButtonData" *ngIf="actions['Capitalized Income']"></mifosx-make-repayment>
<mifosx-make-repayment [dataObject]="actionButtonData" *ngIf="actions['Goodwill Credit']"></mifosx-make-repayment>
<mifosx-make-repayment
[dataObject]="actionButtonData"
@@ -51,6 +51,7 @@ export class LoanAccountActionsComponent {
'Re-Amortize': boolean;
'Interest Payment Waiver': boolean;
'Add Interest Pause': boolean;
'Capitalized Income': boolean;
} = {
Close: false,
'Undo Approval': false,
@@ -86,7 +87,8 @@ export class LoanAccountActionsComponent {
'Re-Age': false,
'Re-Amortize': false,
'Interest Payment Waiver': false,
'Add Interest Pause': false
'Add Interest Pause': false,
'Capitalized Income': false
};
actionButtonData: any;
@@ -21,7 +21,7 @@
</mat-error>
</mat-form-field>
<div fxLayout="row wrap" class="content">
<div fxLayout="row wrap" class="content" *ngIf="showDetails()">
<div fxFlex="50%" class="mat-body-strong">
{{ 'Principal' | translate }}
</div>
@@ -33,6 +33,8 @@ export class MakeRepaymentComponent implements OnInit {
repaymentLoanForm: UntypedFormGroup;
currency: Currency | null = null;
command: string | null = null;
/**
* @param {FormBuilder} formBuilder Form Builder.
* @param {LoansService} loanService Loan Service.
@@ -62,6 +64,7 @@ export class MakeRepaymentComponent implements OnInit {
if (this.dataObject.currency) {
this.currency = this.dataObject.currency;
}
this.command = this.dataObject.type.code.split('.')[1];
}
/**
@@ -110,6 +113,10 @@ export class MakeRepaymentComponent implements OnInit {
}
}
showDetails(): boolean {
return !['capitalizedIncome'].includes(this.command);
}
/** Submits the repayment form */
submit() {
const repaymentLoanFormData = this.repaymentLoanForm.value;
@@ -124,9 +131,8 @@ export class MakeRepaymentComponent implements OnInit {
dateFormat,
locale
};
const command = this.dataObject.type.code.split('.')[1];
data['transactionAmount'] = data['transactionAmount'] * 1;
this.loanService.submitLoanActionButton(this.loanId, data, command).subscribe((response: any) => {
this.loanService.submitLoanActionButton(this.loanId, data, this.command).subscribe((response: any) => {
this.router.navigate(['../../transactions'], { relativeTo: this.route });
});
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
/** Custom Services */
@@ -15,7 +15,7 @@ import { SettingsService } from 'app/settings/settings.service';
templateUrl: './loan-documents-tab.component.html',
styleUrls: ['./loan-documents-tab.component.scss']
})
export class LoanDocumentsTabComponent {
export class LoanDocumentsTabComponent implements OnInit {
/** Stores the resolved loan documents data */
entityDocuments: any;
/** Loan account Id */
@@ -38,6 +38,12 @@ export class LoanDocumentsTabComponent {
});
}
ngOnInit(): void {
this.route.parent.params.subscribe((params) => {
this.entityId = params['loanId'];
});
}
getLoanDocumentsData(data: any) {
data.forEach((ele: any) => {
ele.docUrl =
@@ -82,6 +82,12 @@ export class LoansViewComponent implements OnInit {
}
ngOnInit() {
this.route.params.subscribe((params) => {
if (this.loanId != params['loanId']) {
this.loanId = params['loanId'];
this.reload();
}
});
this.recalculateInterest = this.loanDetailsData.recalculateInterest || true;
this.status = this.loanDetailsData.status.value;
if (this.loanStatus.active && this.loanDetailsData.multiDisburseLoan) {
@@ -129,6 +135,14 @@ export class LoansViewComponent implements OnInit {
taskPermissionName: 'DISBURSE_LOAN'
});
} else if (this.status === 'Active') {
if (this.loanDetailsData.enableIncomeCapitalization) {
this.buttonConfig.addButton({
name: 'Capitalized Income',
icon: 'coins',
taskPermissionName: 'CAPITALIZED_INCOME_LOAN'
});
}
if (this.loanDetailsData.canDisburse || this.loanDetailsData.multiDisburseLoan) {
this.buttonConfig.addButton({
name: 'Disburse',
@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
/** Custom Components */
@@ -12,7 +12,7 @@ import { AuthenticationService } from '../../../core/authentication/authenticati
templateUrl: './notes-tab.component.html',
styleUrls: ['./notes-tab.component.scss']
})
export class NotesTabComponent {
export class NotesTabComponent implements OnInit {
entityId: string;
username: string;
entityNotes: any;
@@ -30,6 +30,12 @@ export class NotesTabComponent {
});
}
ngOnInit(): void {
this.route.parent.params.subscribe((params) => {
this.entityId = params['loanId'];
});
}
addNote(noteContent: any) {
this.loansService.createLoanNote(this.entityId, noteContent).subscribe((response: any) => {
this.entityNotes.push({
@@ -112,7 +112,6 @@ export class ViewTransactionComponent implements OnInit {
});
this.clientId = this.route.snapshot.params['clientId'];
this.loanId = this.route.snapshot.params['loanId'];
console.log(this.transactionType);
}
ngOnInit(): void {
@@ -191,18 +191,6 @@
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
<mat-error *ngIf="chargeForm.controls.amount.hasError('pattern') && currencyDecimalPlaces !== undefined">
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.must be' | translate }}
<strong
>{{ 'labels.commons.a positive number with' | translate }}
{{ currencyDecimalPlaces ? 'up to ' + currencyDecimalPlaces : 'no' }}
{{ 'labels.inputs.decimal places' | translate }}</strong
>
</mat-error>
<mat-error *ngIf="chargeForm.controls.amount.hasError('pattern') && currencyDecimalPlaces === undefined">
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.must be' | translate }}
<strong>{{ 'labels.commons.a positive number' | translate }}</strong>
</mat-error>
</mat-form-field>
<!--
* minCap and maxCap only allowed for loan ,shares and savings entitites
@@ -217,7 +205,11 @@
<mat-form-field fxFlex="48%" *ngIf="showMinMaxCap()">
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
<input matInput formControlName="maxCap" />
<input matInput [min]="chargeForm.value.minCap" formControlName="maxCap" />
<mat-error *ngIf="chargeForm.errors?.minGreaterThanMax">
{{ 'labels.inputs.Maximum Charge Cap' | translate }} ({{ repeatEveryLabel }})
<strong>{{ 'labels.commons.must higher than Minimum Charge Cap' | translate }}</strong>
</mat-error>
</mat-form-field>
<div fxFlex="48%" fxLayout="row" fxLayoutGap="2%" fxLayout.lt-md="column">
@@ -7,6 +7,7 @@ import { Router, ActivatedRoute } from '@angular/router';
import { ProductsService } from '../../products.service';
import { SettingsService } from 'app/settings/settings.service';
import { Dates } from 'app/core/utils/dates';
import { minLessThanOrEqualMaxValidator } from 'app/shared/validators/min-max-values.validator';
/**
* Create charge component.
@@ -79,39 +80,40 @@ export class CreateChargeComponent implements OnInit {
* Creates the charge form.
*/
createChargeForm() {
this.chargeForm = this.formBuilder.group({
chargeAppliesTo: [
'',
Validators.required
],
name: [
'',
Validators.required
],
currencyCode: [
'',
Validators.required
],
chargeTimeType: [
'',
Validators.required
],
chargeCalculationType: [
'',
Validators.required
],
amount: [
'',
[
Validators.required,
Validators.pattern('^\\s*(?=.*[1-9])\\d*(?:\\.\\d+)?\\s*$')]
],
active: [false],
penalty: [false],
taxGroupId: [''],
minCap: [''],
maxCap: ['']
});
this.chargeForm = this.formBuilder.group(
{
chargeAppliesTo: [
'',
Validators.required
],
name: [
'',
Validators.required
],
currencyCode: [
'',
Validators.required
],
chargeTimeType: [
'',
Validators.required
],
chargeCalculationType: [
'',
Validators.required
],
amount: [
'',
Validators.required
],
active: [false],
penalty: [false],
taxGroupId: [''],
minCap: [''],
maxCap: ['']
},
{ validators: minLessThanOrEqualMaxValidator('minCap', 'maxCap') }
);
}
/**
@@ -275,15 +277,6 @@ export class CreateChargeComponent implements OnInit {
this.currencyDecimalPlaces = this.chargesTemplateData.currencyOptions.find(
(currency: any) => currency.code === currencyCode
).decimalPlaces;
if (this.currencyDecimalPlaces === 0) {
this.chargeForm.get('amount').setValidators([
Validators.required,
Validators.pattern('^[1-9]\\d*$')]);
} else {
this.chargeForm.get('amount').setValidators([
Validators.required,
Validators.pattern(`^\\s*(?=.*[1-9])\\d*(\\.\\d{1,${this.currencyDecimalPlaces}})?\\s*$`)]);
}
});
}
@@ -113,6 +113,12 @@
>
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="minCap" />
<mat-error
*ngIf="chargeForm.controls.maxCap.hasError('minGreaterThanMax') || chargeForm.errors?.minGreaterThanMax"
>
{{ 'labels.inputs.Minimum Charge Cap' | translate }} ({{ repeatEveryLabel }})
<strong>{{ 'labels.commons.must lower than Maximum Charge Cap' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field
fxFlex="48%"
@@ -131,7 +137,11 @@
"
>
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="maxCap" />
<input matInput [min]="chargeForm.value.minCap" autofocus formControlName="maxCap" />
<mat-error *ngIf="chargeForm.hasError('minGreaterThanMax') || chargeForm.errors?.minGreaterThanMax">
{{ 'labels.inputs.Maximum Charge Cap' | translate }} ({{ repeatEveryLabel }})
<strong>{{ 'labels.commons.must be equal or greater than Minimum Charge Cap' | translate }}</strong>
</mat-error>
</mat-form-field>
<mifosx-gl-account-selector
@@ -6,6 +6,7 @@ import { ActivatedRoute, Router } from '@angular/router';
/** Custom Services */
import { ProductsService } from 'app/products/products.service';
import { SettingsService } from 'app/settings/settings.service';
import { minLessThanOrEqualMaxValidator } from 'app/shared/validators/min-max-values.validator';
/**
* Edit Charge component.
@@ -73,36 +74,39 @@ export class EditChargeComponent implements OnInit {
editChargeForm() {
this.showFeeOptions = this.chargeData.feeInterval && this.chargeData.feeInterval > 0;
this.chargeForm = this.formBuilder.group({
name: [
this.chargeData.name,
Validators.required
],
chargeAppliesTo: [
{ value: this.chargeData.chargeAppliesTo.id, disabled: true },
Validators.required
],
currencyCode: [
this.chargeData.currency.code,
Validators.required
],
amount: [
this.chargeData.amount,
Validators.required
],
active: [this.chargeData.active],
penalty: [this.chargeData.penalty],
minCap: [this.chargeData.minCap],
maxCap: [this.chargeData.maxCap],
chargeTimeType: [
this.chargeData.chargeTimeType.id,
Validators.required
],
chargeCalculationType: [
this.chargeData.chargeCalculationType.id,
Validators.required
]
});
this.chargeForm = this.formBuilder.group(
{
name: [
this.chargeData.name,
Validators.required
],
chargeAppliesTo: [
{ value: this.chargeData.chargeAppliesTo.id, disabled: true },
Validators.required
],
currencyCode: [
this.chargeData.currency.code,
Validators.required
],
amount: [
this.chargeData.amount,
Validators.required
],
active: [this.chargeData.active],
penalty: [this.chargeData.penalty],
minCap: [this.chargeData.minCap],
maxCap: [this.chargeData.maxCap],
chargeTimeType: [
this.chargeData.chargeTimeType.id,
Validators.required
],
chargeCalculationType: [
this.chargeData.chargeCalculationType.id,
Validators.required
]
},
{ validators: minLessThanOrEqualMaxValidator('minCap', 'maxCap') }
);
switch (this.chargeData.chargeAppliesTo.value) {
case 'Loan': {
this.chargeTimeTypeOptions = this.chargeData.loanChargeTimeTypeOptions;
@@ -50,7 +50,7 @@
</div>
<div fxFlex="50%">
{{ chargeData.amount | formatNumber }}
{{ chargeData.amount }}
</div>
<div fxFlex="50%" class="mat-body-strong" *ngIf="minCap">
@@ -878,6 +878,11 @@
<span fxFlex="47%">{{ 'labels.inputs.Income capitalization strategy' | translate }}:</span>
<span fxFlex="53%">{{ loanProduct.capitalizedIncomeStrategy?.value | translateKey: 'catalogs' }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableIncomeCapitalization">
<span fxFlex="47%">{{ 'labels.inputs.Income type' | translate }}:</span>
<span fxFlex="53%">{{ loanProduct.capitalizedIncomeType?.value | translateKey: 'catalogs' }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>{{ 'labels.heading.Accounting' | translate }}</h3>
@@ -1011,6 +1016,14 @@
[withTitle]="'47%'"
>
</mifosx-gl-account-display>
<mifosx-gl-account-display
fxFlex="100%"
*ngIf="accountingMappings.incomeFromCapitalizationAccount"
[accountTitle]="'Income capitalization'"
[glAccount]="accountingMappings.incomeFromCapitalizationAccount"
[withTitle]="'47%'"
>
</mifosx-gl-account-display>
<h4 fxFlexFill class="mat-h4">{{ 'labels.heading.Expenses' | translate }}</h4>
@@ -1054,6 +1067,14 @@
[withTitle]="'47%'"
>
</mifosx-gl-account-display>
<mifosx-gl-account-display
fxFlex="100%"
*ngIf="accountingMappings.deferredIncomeLiabilityAccount"
[accountTitle]="'Deferred income'"
[glAccount]="accountingMappings.deferredIncomeLiabilityAccount"
[withTitle]="'47%'"
>
</mifosx-gl-account-display>
<div *ngIf="isAdvancedAccountingEnabled()" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
@@ -152,6 +152,10 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
this.loanProduct.incomeFromChargeOffPenaltyAccountId,
incomeAccountData
),
incomeFromCapitalizationAccount: this.glAccountLookUp(
this.loanProduct.incomeFromCapitalizationAccountId,
incomeAccountData
),
writeOffAccount: this.glAccountLookUp(this.loanProduct.writeOffAccountId, expenseAccountData),
goodwillCreditAccount: this.glAccountLookUp(this.loanProduct.goodwillCreditAccountId, expenseAccountData),
@@ -161,6 +165,10 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
overpaymentLiabilityAccount: this.glAccountLookUp(
this.loanProduct.overpaymentLiabilityAccountId,
liabilityAccountData
),
deferredIncomeLiabilityAccount: this.glAccountLookUp(
this.loanProduct.deferredIncomeLiabilityAccountId,
liabilityAccountData
)
};
@@ -293,6 +301,11 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
this.loanProductsTemplate.capitalizedIncomeStrategyOptions
);
this.loanProduct.capitalizedIncomeStrategy = optionValue;
optionValue = this.optionDataLookUp(
this.loanProduct.capitalizedIncomeType,
this.loanProductsTemplate.capitalizedIncomeTypeOptions
);
this.loanProduct.capitalizedIncomeType = optionValue;
}
optionValue = this.optionDataLookUp(
this.loanProduct.interestRateFrequencyType,
@@ -98,7 +98,9 @@
[capitalizedIncome]="capitalizedIncome"
[capitalizedIncomeCalculationTypeOptions]="loanProductsTemplate.capitalizedIncomeCalculationTypeOptions"
[capitalizedIncomeStrategyOptions]="loanProductsTemplate.capitalizedIncomeStrategyOptions"
[capitalizedIncomeTypeOptions]="loanProductsTemplate.capitalizedIncomeTypeOptions"
(setCapitalizedIncome)="setCapitalizedIncome($event)"
(setViewChildForm)="setViewChildForm($event)"
>
</mifosx-loan-product-capitalized-income-step>
@@ -112,6 +114,7 @@
[loanProductsTemplate]="loanProductsTemplate"
[accountingRuleData]="accountingRuleData"
[loanProductFormValid]="loanProductFormValid"
[capitalizedIncome]="capitalizedIncome"
>
</mifosx-loan-product-accounting-step>
</mat-step>
@@ -23,6 +23,7 @@ import {
import { Accounting } from 'app/core/utils/accounting';
import { StringEnumOptionData } from '../../../shared/models/option-data.model';
import { LoanProductCapitalizedIncomeStepComponent } from '../loan-product-stepper/loan-product-capitalized-income-step/loan-product-capitalized-income-step.component';
import { UntypedFormGroup } from '@angular/forms';
@Component({
selector: 'mifosx-create-loan-product',
@@ -56,6 +57,7 @@ export class CreateLoanProductComponent implements OnInit {
advancedCreditAllocations: AdvancedPaymentAllocation[] = [];
capitalizedIncome: CapitalizedIncome | null = null;
loanIncomeCapitalizationForm: UntypedFormGroup;
/**
* @param {ActivatedRoute} route Activated Route.
@@ -115,8 +117,9 @@ export class CreateLoanProductComponent implements OnInit {
if (this.loanProductsTemplate.enableIncomeCapitalization) {
this.capitalizedIncome = {
enableIncomeCapitalization: true,
incomeCapitalizationCalculationType: this.loanProductsTemplate.capitalizedIncomeCalculationTypeOptions[0],
incomeCapitalizationStrategy: this.loanProductsTemplate.capitalizedIncomeStrategyOptions[0]
capitalizedIncomeCalculationType: this.loanProductsTemplate.capitalizedIncomeCalculationTypeOptions[0],
capitalizedIncomeStrategy: this.loanProductsTemplate.capitalizedIncomeStrategyOptions[0],
capitalizedIncomeType: this.loanProductsTemplate.capitalizedIncomeTypeOptions[0]
};
} else {
this.capitalizedIncome = {
@@ -150,6 +153,10 @@ export class CreateLoanProductComponent implements OnInit {
}
}
setViewChildForm(viewChildForm: UntypedFormGroup): void {
this.loanIncomeCapitalizationForm = viewChildForm;
}
get loanProductSettingsForm() {
return this.loanProductSettingsStep.loanProductSettingsForm;
}
@@ -158,20 +165,25 @@ export class CreateLoanProductComponent implements OnInit {
return this.loanProductAccountingStep.loanProductAccountingForm;
}
get loanIncomeCapitalizationForm() {
if (this.loanProductCapitalizedIncomeStep != null) {
return this.loanProductCapitalizedIncomeStep.loanIncomeCapitalizationForm;
}
}
get loanProductFormValid() {
return (
this.loanProductDetailsForm.valid &&
this.loanProductCurrencyForm.valid &&
this.loanProductTermsForm.valid &&
this.loanProductSettingsForm.valid &&
this.loanProductAccountingForm.valid
);
if (this.isAdvancedPaymentStrategy) {
return (
this.loanProductDetailsForm.valid &&
this.loanProductCurrencyForm.valid &&
this.loanProductTermsForm.valid &&
this.loanProductSettingsForm.valid &&
this.loanIncomeCapitalizationForm.valid &&
this.loanProductAccountingForm.valid
);
} else {
return (
this.loanProductDetailsForm.valid &&
this.loanProductCurrencyForm.valid &&
this.loanProductTermsForm.valid &&
this.loanProductSettingsForm.valid &&
this.loanProductAccountingForm.valid
);
}
}
get loanProduct() {
@@ -190,8 +202,9 @@ export class CreateLoanProductComponent implements OnInit {
if (this.capitalizedIncome != null) {
loanProduct['enableIncomeCapitalization'] = this.capitalizedIncome.enableIncomeCapitalization;
if (this.capitalizedIncome.enableIncomeCapitalization) {
loanProduct['capitalizedIncomeCalculationType'] = this.capitalizedIncome.incomeCapitalizationCalculationType;
loanProduct['capitalizedIncomeStrategy'] = this.capitalizedIncome.incomeCapitalizationStrategy;
loanProduct['capitalizedIncomeCalculationType'] = this.capitalizedIncome.capitalizedIncomeCalculationType;
loanProduct['capitalizedIncomeStrategy'] = this.capitalizedIncome.capitalizedIncomeStrategy;
loanProduct['capitalizedIncomeType'] = this.capitalizedIncome.capitalizedIncomeType;
}
}
}
@@ -210,6 +223,7 @@ export class CreateLoanProductComponent implements OnInit {
);
} else {
delete loanProduct['supportedInterestRefundTypes'];
delete loanProduct['daysInYearCustomStrategy'];
}
delete loanProduct['useDueForRepaymentsConfigurations'];
@@ -100,7 +100,9 @@
[capitalizedIncome]="capitalizedIncome"
[capitalizedIncomeCalculationTypeOptions]="loanProductAndTemplate.capitalizedIncomeCalculationTypeOptions"
[capitalizedIncomeStrategyOptions]="loanProductAndTemplate.capitalizedIncomeStrategyOptions"
[capitalizedIncomeTypeOptions]="loanProductAndTemplate.capitalizedIncomeTypeOptions"
(setCapitalizedIncome)="setCapitalizedIncome($event)"
(setViewChildForm)="setViewChildForm($event)"
>
</mifosx-loan-product-capitalized-income-step>
@@ -114,6 +116,7 @@
[loanProductsTemplate]="loanProductAndTemplate"
[accountingRuleData]="accountingRuleData"
[loanProductFormValid]="loanProductFormValidAndNotPristine"
[capitalizedIncome]="capitalizedIncome"
>
</mifosx-loan-product-accounting-step>
</mat-step>
@@ -26,6 +26,7 @@ import { Accounting } from 'app/core/utils/accounting';
import { LoanProductInterestRefundStepComponent } from '../loan-product-stepper/loan-product-interest-refund-step/loan-product-interest-refund-step.component';
import { StringEnumOptionData } from '../../../shared/models/option-data.model';
import { LoanProductCapitalizedIncomeStepComponent } from '../loan-product-stepper/loan-product-capitalized-income-step/loan-product-capitalized-income-step.component';
import { UntypedFormGroup } from '@angular/forms';
@Component({
selector: 'mifosx-edit-loan-product',
@@ -60,6 +61,7 @@ export class EditLoanProductComponent implements OnInit {
supportedInterestRefundTypes: StringEnumOptionData[] = [];
capitalizedIncome: CapitalizedIncome | null = null;
loanIncomeCapitalizationForm: UntypedFormGroup | null = null;
/**
* @param {ActivatedRoute} route Activated Route.
@@ -99,8 +101,9 @@ export class EditLoanProductComponent implements OnInit {
if (this.loanProductAndTemplate.enableIncomeCapitalization) {
this.capitalizedIncome = {
enableIncomeCapitalization: true,
incomeCapitalizationCalculationType: this.loanProductAndTemplate.capitalizedIncomeCalculationType.id,
incomeCapitalizationStrategy: this.loanProductAndTemplate.capitalizedIncomeStrategy.id
capitalizedIncomeCalculationType: this.loanProductAndTemplate.capitalizedIncomeCalculationType.id,
capitalizedIncomeStrategy: this.loanProductAndTemplate.capitalizedIncomeStrategy.id,
capitalizedIncomeType: this.loanProductAndTemplate.capitalizedIncomeType.id
};
} else {
this.capitalizedIncome = {
@@ -132,10 +135,8 @@ export class EditLoanProductComponent implements OnInit {
}
}
get loanIncomeCapitalizationForm() {
if (this.loanProductCapitalizedIncomeStep != null) {
return this.loanProductCapitalizedIncomeStep.loanIncomeCapitalizationForm;
}
setViewChildForm(viewChildForm: UntypedFormGroup): void {
this.loanIncomeCapitalizationForm = viewChildForm;
}
advancePaymentStrategy(value: string): void {
@@ -180,20 +181,40 @@ export class EditLoanProductComponent implements OnInit {
}
get loanProductFormValidAndNotPristine() {
return (
this.loanProductDetailsForm.valid &&
this.loanProductCurrencyForm.valid &&
this.loanProductTermsForm.valid &&
this.loanProductSettingsForm.valid &&
this.loanProductAccountingForm.valid &&
(!this.loanProductDetailsForm.pristine ||
!this.loanProductCurrencyForm.pristine ||
!this.loanProductTermsForm.pristine ||
!this.loanProductSettingsForm.pristine ||
!this.loanProductChargesStep.pristine ||
!this.loanProductAccountingForm.pristine ||
this.wasPaymentAllocationChanged)
);
if (this.isAdvancedPaymentStrategy) {
return (
this.loanProductDetailsForm.valid &&
this.loanProductCurrencyForm.valid &&
this.loanProductTermsForm.valid &&
this.loanProductSettingsForm.valid &&
this.loanProductAccountingForm.valid &&
this.loanIncomeCapitalizationForm != null &&
this.loanIncomeCapitalizationForm.valid &&
(!this.loanProductDetailsForm.pristine ||
!this.loanProductCurrencyForm.pristine ||
!this.loanProductTermsForm.pristine ||
!this.loanProductSettingsForm.pristine ||
!this.loanProductChargesStep.pristine ||
!this.loanProductAccountingForm.pristine ||
!this.loanIncomeCapitalizationForm.pristine ||
this.wasPaymentAllocationChanged)
);
} else {
return (
this.loanProductDetailsForm.valid &&
this.loanProductCurrencyForm.valid &&
this.loanProductTermsForm.valid &&
this.loanProductSettingsForm.valid &&
this.loanProductAccountingForm.valid &&
(!this.loanProductDetailsForm.pristine ||
!this.loanProductCurrencyForm.pristine ||
!this.loanProductTermsForm.pristine ||
!this.loanProductSettingsForm.pristine ||
!this.loanProductChargesStep.pristine ||
!this.loanProductAccountingForm.pristine ||
this.wasPaymentAllocationChanged)
);
}
}
get loanProduct() {
@@ -216,8 +237,9 @@ export class EditLoanProductComponent implements OnInit {
if (this.capitalizedIncome != null) {
loanProduct['enableIncomeCapitalization'] = this.capitalizedIncome.enableIncomeCapitalization;
if (this.capitalizedIncome.enableIncomeCapitalization) {
loanProduct['capitalizedIncomeCalculationType'] = this.capitalizedIncome.incomeCapitalizationCalculationType;
loanProduct['capitalizedIncomeStrategy'] = this.capitalizedIncome.incomeCapitalizationStrategy;
loanProduct['capitalizedIncomeCalculationType'] = this.capitalizedIncome.capitalizedIncomeCalculationType;
loanProduct['capitalizedIncomeStrategy'] = this.capitalizedIncome.capitalizedIncomeStrategy;
loanProduct['capitalizedIncomeType'] = this.capitalizedIncome.capitalizedIncomeType;
}
}
}
@@ -236,6 +258,7 @@ export class EditLoanProductComponent implements OnInit {
);
} else {
delete loanProduct['supportedInterestRefundTypes'];
delete loanProduct['daysInYearCustomStrategy'];
}
delete loanProduct['useDueForRepaymentsConfigurations'];
@@ -189,6 +189,16 @@
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
*ngIf="capitalizedIncome?.enableIncomeCapitalization"
fxFlex="48%"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromCapitalizationAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income capitalization'"
>
</mifosx-gl-account-selector>
<mat-divider fxFlex="98%"></mat-divider>
<h4 fxFlex="98%" class="mat-h4">{{ 'labels.heading.Expenses' | translate }}</h4>
@@ -242,6 +252,16 @@
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
*ngIf="capitalizedIncome?.enableIncomeCapitalization"
fxFlex="48%"
[inputFormControl]="loanProductAccountingForm.controls.deferredIncomeLiabilityAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Deferred income'"
>
</mifosx-gl-account-selector>
<mat-divider fxFlex="98%"></mat-divider>
<mat-checkbox fxFlex="73%" formControlName="advancedAccountingRules">{{
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
@@ -9,16 +9,18 @@ import { TranslateService } from '@ngx-translate/core';
import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base';
import { ChargeOffReasonToExpenseAccountMapping } from 'app/shared/models/general.model';
import { CapitalizedIncome } from '../loan-product-payment-strategy-step/payment-allocation-model';
@Component({
selector: 'mifosx-loan-product-accounting-step',
templateUrl: './loan-product-accounting-step.component.html',
styleUrls: ['./loan-product-accounting-step.component.scss']
})
export class LoanProductAccountingStepComponent implements OnInit {
export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
@Input() loanProductsTemplate: any;
@Input() accountingRuleData: any;
@Input() loanProductFormValid: boolean;
@Input() capitalizedIncome: CapitalizedIncome;
loanProductAccountingForm: UntypedFormGroup;
@@ -61,6 +63,10 @@ export class LoanProductAccountingStepComponent implements OnInit {
this.setConditionalControls();
}
ngOnChanges(changes: SimpleChanges): void {
this.setCapitalizedIncomeControls();
}
ngOnInit() {
this.chargeData = this.loanProductsTemplate.chargeOptions || [];
this.penaltyData = this.loanProductsTemplate.penaltyOptions || [];
@@ -79,6 +85,7 @@ export class LoanProductAccountingStepComponent implements OnInit {
});
const accountingMappings = this.loanProductsTemplate.accountingMappings;
this.setCapitalizedIncomeControls();
switch (this.loanProductsTemplate.accountingRule.id) {
case 3:
case 4:
@@ -90,6 +97,12 @@ export class LoanProductAccountingStepComponent implements OnInit {
this.loanProductAccountingForm.patchValue({
enableAccrualActivityPosting: this.loanProductsTemplate.enableAccrualActivityPosting
});
if (this.capitalizedIncome.enableIncomeCapitalization) {
this.loanProductAccountingForm.patchValue({
deferredIncomeLiabilityAccountId: accountingMappings.deferredIncomeLiabilityAccount.id,
incomeFromCapitalizationAccountId: accountingMappings.incomeFromCapitalizationAccount.id
});
}
/* falls through */
case 2:
this.loanProductAccountingForm.patchValue({
@@ -524,4 +537,22 @@ export class LoanProductAccountingStepComponent implements OnInit {
get loanProductAccounting() {
return this.loanProductAccountingForm.value;
}
setCapitalizedIncomeControls() {
if (this.isAccountingAccrualBased) {
if (this.capitalizedIncome.enableIncomeCapitalization) {
this.loanProductAccountingForm.addControl(
'deferredIncomeLiabilityAccountId',
new UntypedFormControl('', Validators.required)
);
this.loanProductAccountingForm.addControl(
'incomeFromCapitalizationAccountId',
new UntypedFormControl('', Validators.required)
);
} else {
this.loanProductAccountingForm.removeControl('deferredIncomeLiabilityAccountId');
this.loanProductAccountingForm.removeControl('incomeFromCapitalizationAccountId');
}
}
}
}
@@ -6,7 +6,7 @@
<mat-form-field fxFlex="48%" *ngIf="enableIncomeCapitalization">
<mat-label>{{ 'labels.inputs.Income capitalization calculation type' | translate }}</mat-label>
<mat-select formControlName="incomeCapitalizationCalculationType" required>
<mat-select formControlName="capitalizedIncomeCalculationType" required>
<mat-option
*ngFor="let capitalizedIncomeCalculationType of capitalizedIncomeCalculationTypeOptions"
[value]="capitalizedIncomeCalculationType.id"
@@ -17,7 +17,7 @@
</mat-form-field>
<mat-form-field fxFlex="48%" *ngIf="enableIncomeCapitalization">
<mat-label>{{ 'labels.inputs.Income capitalization strategy' | translate }}</mat-label>
<mat-select formControlName="incomeCapitalizationStrategy" required>
<mat-select formControlName="capitalizedIncomeStrategy" required>
<mat-option
*ngFor="let capitalizedIncomeStrategy of capitalizedIncomeStrategyOptions"
[value]="capitalizedIncomeStrategy.id"
@@ -26,5 +26,16 @@
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%" *ngIf="enableIncomeCapitalization">
<mat-label>{{ 'labels.inputs.Income type' | translate }}</mat-label>
<mat-select formControlName="capitalizedIncomeType" required>
<mat-option
*ngFor="let capitalizedIncomeType of capitalizedIncomeTypeOptions"
[value]="capitalizedIncomeType.id"
>
{{ capitalizedIncomeType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</form>
@@ -12,12 +12,14 @@ export class LoanProductCapitalizedIncomeStepComponent implements OnChanges {
@Input() capitalizedIncome: CapitalizedIncome;
@Input() capitalizedIncomeCalculationTypeOptions: StringEnumOptionData[];
@Input() capitalizedIncomeStrategyOptions: StringEnumOptionData[];
@Input() capitalizedIncomeTypeOptions: StringEnumOptionData[];
loanIncomeCapitalizationForm: UntypedFormGroup;
enableIncomeCapitalization: boolean;
@Output() setCapitalizedIncome = new EventEmitter<CapitalizedIncome>();
@Output() setViewChildForm = new EventEmitter<UntypedFormGroup>();
constructor(private formBuilder: UntypedFormBuilder) {
this.enableIncomeCapitalization =
@@ -30,12 +32,16 @@ export class LoanProductCapitalizedIncomeStepComponent implements OnChanges {
if (this.enableIncomeCapitalization) {
this.loanIncomeCapitalizationForm = this.formBuilder.group({
enableIncomeCapitalization: [this.enableIncomeCapitalization],
incomeCapitalizationCalculationType: [
this.capitalizedIncome.incomeCapitalizationCalculationType,
capitalizedIncomeCalculationType: [
this.capitalizedIncome.capitalizedIncomeCalculationType,
Validators.required
],
incomeCapitalizationStrategy: [
this.capitalizedIncome.incomeCapitalizationStrategy,
capitalizedIncomeStrategy: [
this.capitalizedIncome.capitalizedIncomeStrategy,
Validators.required
],
capitalizedIncomeType: [
this.capitalizedIncome.capitalizedIncomeType,
Validators.required
]
});
@@ -44,6 +50,7 @@ export class LoanProductCapitalizedIncomeStepComponent implements OnChanges {
enableIncomeCapitalization: [this.enableIncomeCapitalization]
});
}
this.setViewChildForm.emit(this.loanIncomeCapitalizationForm);
}
ngOnChanges(changes: SimpleChanges): void {
@@ -51,66 +58,87 @@ export class LoanProductCapitalizedIncomeStepComponent implements OnChanges {
if (this.enableIncomeCapitalization) {
this.loanIncomeCapitalizationForm.patchValue({
enableIncomeCapitalization: this.enableIncomeCapitalization,
incomeCapitalizationCalculationType: this.capitalizedIncome.incomeCapitalizationCalculationType,
incomeCapitalizationStrategy: this.capitalizedIncome.incomeCapitalizationStrategy
capitalizedIncomeCalculationType: this.capitalizedIncome.capitalizedIncomeCalculationType,
capitalizedIncomeStrategy: this.capitalizedIncome.capitalizedIncomeStrategy,
capitalizedIncomeType: this.capitalizedIncome.capitalizedIncomeType
});
}
this.setViewChildForm.emit(this.loanIncomeCapitalizationForm);
}
setConditionalControls() {
this.loanIncomeCapitalizationForm.get('enableIncomeCapitalization').valueChanges.subscribe((enabled: boolean) => {
this.enableIncomeCapitalization = enabled;
if (this.enableIncomeCapitalization) {
const incomeCapitalizationCalculationType =
this.capitalizedIncome.incomeCapitalizationCalculationType == ''
const capitalizedIncomeCalculationType =
!this.capitalizedIncome.capitalizedIncomeCalculationType ||
this.capitalizedIncome.capitalizedIncomeCalculationType == ''
? this.capitalizedIncomeCalculationTypeOptions[0].id
: this.capitalizedIncome.incomeCapitalizationCalculationType;
: this.capitalizedIncome.capitalizedIncomeCalculationType;
this.loanIncomeCapitalizationForm.addControl(
'incomeCapitalizationCalculationType',
new UntypedFormControl(
this.capitalizedIncome.incomeCapitalizationCalculationType ||
this.capitalizedIncomeCalculationTypeOptions[0].id,
Validators.required
)
'capitalizedIncomeCalculationType',
new UntypedFormControl(capitalizedIncomeCalculationType, Validators.required)
);
const incomeCapitalizationStrategy =
this.capitalizedIncome.incomeCapitalizationStrategy == ''
const capitalizedIncomeStrategy =
!this.capitalizedIncome.capitalizedIncomeStrategy || this.capitalizedIncome.capitalizedIncomeStrategy == ''
? this.capitalizedIncomeStrategyOptions[0].id
: this.capitalizedIncome.incomeCapitalizationStrategy;
: this.capitalizedIncome.capitalizedIncomeStrategy;
this.loanIncomeCapitalizationForm.addControl(
'incomeCapitalizationStrategy',
new UntypedFormControl(incomeCapitalizationStrategy, Validators.required)
'capitalizedIncomeStrategy',
new UntypedFormControl(capitalizedIncomeStrategy, Validators.required)
);
const capitalizedIncomeType =
!this.capitalizedIncome.capitalizedIncomeType || this.capitalizedIncome.capitalizedIncomeType == ''
? this.capitalizedIncomeTypeOptions[0].id
: this.capitalizedIncome.capitalizedIncomeType;
this.loanIncomeCapitalizationForm.addControl(
'capitalizedIncomeType',
new UntypedFormControl(capitalizedIncomeType, Validators.required)
);
this.setCapitalizedIncome.emit({
enableIncomeCapitalization: true,
incomeCapitalizationCalculationType: incomeCapitalizationCalculationType,
incomeCapitalizationStrategy: incomeCapitalizationStrategy
capitalizedIncomeCalculationType: capitalizedIncomeCalculationType,
capitalizedIncomeStrategy: capitalizedIncomeStrategy,
capitalizedIncomeType: capitalizedIncomeType
});
this.loanIncomeCapitalizationForm
.get('incomeCapitalizationCalculationType')
.get('capitalizedIncomeCalculationType')
.valueChanges.subscribe((newValue: string) => {
this.setCapitalizedIncome.emit({
enableIncomeCapitalization: true,
incomeCapitalizationCalculationType: newValue,
incomeCapitalizationStrategy: this.loanIncomeCapitalizationForm.value.incomeCapitalizationStrategy
capitalizedIncomeCalculationType: newValue,
capitalizedIncomeStrategy: this.loanIncomeCapitalizationForm.value.capitalizedIncomeStrategy,
capitalizedIncomeType: this.loanIncomeCapitalizationForm.value.capitalizedIncomeType
});
});
this.loanIncomeCapitalizationForm
.get('incomeCapitalizationStrategy')
.get('capitalizedIncomeStrategy')
.valueChanges.subscribe((newValue: string) => {
this.setCapitalizedIncome.emit({
enableIncomeCapitalization: true,
incomeCapitalizationCalculationType:
this.loanIncomeCapitalizationForm.value.incomeCapitalizationCalculationType,
incomeCapitalizationStrategy: newValue
capitalizedIncomeCalculationType:
this.loanIncomeCapitalizationForm.value.capitalizedIncomeCalculationType,
capitalizedIncomeStrategy: newValue,
capitalizedIncomeType: this.loanIncomeCapitalizationForm.value.capitalizedIncomeType
});
});
this.loanIncomeCapitalizationForm.get('capitalizedIncomeType').valueChanges.subscribe((newValue: string) => {
this.setCapitalizedIncome.emit({
enableIncomeCapitalization: true,
capitalizedIncomeCalculationType: this.loanIncomeCapitalizationForm.value.capitalizedIncomeCalculationType,
capitalizedIncomeStrategy: this.loanIncomeCapitalizationForm.value.capitalizedIncomeStrategy,
capitalizedIncomeType: newValue
});
});
} else {
this.loanIncomeCapitalizationForm.removeControl('incomeCapitalizationCalculationType');
this.loanIncomeCapitalizationForm.removeControl('incomeCapitalizationStrategy');
this.loanIncomeCapitalizationForm.removeControl('capitalizedIncomeCalculationType');
this.loanIncomeCapitalizationForm.removeControl('capitalizedIncomeStrategy');
this.loanIncomeCapitalizationForm.removeControl('capitalizedIncomeType');
this.setCapitalizedIncome.emit({ enableIncomeCapitalization: false });
}
this.setViewChildForm.emit(this.loanIncomeCapitalizationForm);
});
}
}
@@ -44,8 +44,9 @@ export interface CreditAllocation {
export interface CapitalizedIncome {
enableIncomeCapitalization: boolean;
incomeCapitalizationCalculationType?: string;
incomeCapitalizationStrategy?: string;
capitalizedIncomeCalculationType?: string;
capitalizedIncomeStrategy?: string;
capitalizedIncomeType?: string;
}
export class PaymentAllocationTransactionTypes {
@@ -69,6 +69,7 @@ export interface LoanProduct {
enableIncomeCapitalization?: boolean;
capitalizedIncomeCalculationType?: OptionData;
capitalizedIncomeStrategy?: OptionData;
capitalizedIncomeType?: OptionData;
canDefineInstallmentAmount: boolean;
graceOnArrearsAgeing?: number;
@@ -117,6 +118,7 @@ export interface LoanProduct {
accountingMappings?: { [key: string]: AccountingMapping };
fundSourceAccountId?: number;
goodwillCreditAccountId?: number;
incomeFromCapitalizationAccountId?: number;
incomeFromChargeOffFeesAccountId?: number;
incomeFromChargeOffInterestAccountId?: number;
incomeFromChargeOffPenaltyAccountId?: number;
@@ -134,6 +136,7 @@ export interface LoanProduct {
receivablePenaltyAccountId?: number;
transfersInSuspenseAccountId?: number;
writeOffAccountId?: number;
deferredIncomeLiabilityAccountId?: number;
// Advanced Accounting
paymentChannelToFundSourceMappings?: PaymentChannelToFundSourceMapping[];
feeToIncomeAccountMappings?: ChargeToIncomeAccountMapping[];
@@ -170,7 +170,6 @@ export class SavingsAccountChargesStepComponent implements OnInit, OnChanges {
newCharge = { ...charge, feeOnMonthDay: dateMonthDay };
break;
}
console.log(newCharge);
this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1, newCharge);
this.chargesDataSource = this.chargesDataSource.concat([]);
}
+5 -1
View File
@@ -157,7 +157,11 @@ export class SettingsService {
if (localStorage.getItem('mifosXServerURL')) {
return localStorage.getItem('mifosXServerURL');
}
return environment.baseApiUrl;
if (environment.baseApiUrl && environment.baseApiUrl !== '') {
return environment.baseApiUrl;
} else {
return this.servers()[0];
}
}
/**
@@ -3,12 +3,7 @@
<fa-icon icon="building" size="lg"></fa-icon>
</span>
<mat-label>{{ 'labels.inputs.Tenant' | translate }}</mat-label>
<mat-select
[disabled]="!allowSelection()"
[formControl]="tenantSelector"
(selectionChange)="setTenantIdentifier()"
class="tenantselector"
>
<mat-select [formControl]="tenantSelector" (selectionChange)="setTenantIdentifier()" class="tenantselector">
<mat-option *ngFor="let tenant of tenants" [value]="tenant">
{{ tenant }}
</mat-option>
@@ -19,6 +19,11 @@ export class TenantSelectorComponent implements OnInit {
ngOnInit(): void {
this.tenantSelector.setValue(this.settingsService.tenantIdentifier);
if (this.tenants.length > 1) {
this.tenantSelector.enable;
} else {
this.tenantSelector.disable;
}
}
/**
@@ -0,0 +1,16 @@
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function minLessThanOrEqualMaxValidator(minKey: string, maxKey: string): ValidatorFn {
return (group: AbstractControl): ValidationErrors | null => {
const min = group.get(minKey)?.value;
const max = group.get(maxKey)?.value;
if (min != null && max != null) {
if (max * 1 < min * 1) {
return { minGreaterThanMax: true };
}
}
return null;
};
}
@@ -40,7 +40,6 @@ export class ChargesTabComponent implements OnInit {
this.sharesAccountData = data.sharesAccountData;
this.chargesData = this.sharesAccountData.charges;
});
console.log(this.sharesAccountData);
}
ngOnInit() {
@@ -141,7 +141,6 @@ export class CreateHookComponent implements OnInit {
const addEventDialogRef = this.dialog.open(AddEventDialogComponent, {
data: this.hooksTemplateData
});
console.log(this.hooksTemplateData);
addEventDialogRef.afterClosed().subscribe((response: any) => {
if (response) {
@@ -231,9 +231,7 @@ export class ViewRoleComponent implements OnInit {
this.formGroup.controls.roster.disable();
this.checkboxesChanged = false;
this.isDisabled = true;
this.systemService.updateRolePermission(this.roleId, permissionData).subscribe((response: any) => {
console.log('response: ', response);
});
this.systemService.updateRolePermission(this.roleId, permissionData).subscribe((response: any) => {});
}
/**