diff --git a/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.html b/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.html
index 7d294db5b..c0ae61e4d 100644
--- a/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.html
+++ b/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.html
@@ -722,7 +722,7 @@
{{ loanProduct.multiDisburseLoan | yesNo }}
-
+
{{ 'labels.inputs.Maximum Tranche count' | translate }}:
{{ loanProduct.maxTrancheCount }}
@@ -737,7 +737,7 @@
{{ 'labels.heading.Event Settings' | translate }}
-
+
{{
'labels.inputs.Use the Global Configurations values to the Repayment Event (notifications)' | translate
@@ -1252,6 +1252,72 @@
+
+
0"
+ class="flex-100 layout-row-wrap responsive-column"
+ >
+
+ {{ 'labels.heading.Buydown Fee classifications to Income accounts' | translate }}
+
+
+
+
+ | {{ 'labels.inputs.Classification' | translate }} |
+
+ {{ classificationToIncomeAccountMapping.classificationCodeValue.name }}
+ |
+
+
+
+ {{ 'labels.inputs.Income Account' | translate }} |
+
+ ({{ classificationToIncomeAccountMapping.incomeAccount.glCode }})
+ {{ classificationToIncomeAccountMapping.incomeAccount.name }}
+ |
+
+
+
+
+
+
+
+
0"
+ class="flex-100 layout-row-wrap responsive-column"
+ >
+
+ {{ 'labels.heading.Capitalized Income classifications to Income accounts' | translate }}
+
+
+
+
+ | {{ 'labels.inputs.Classification' | translate }} |
+
+ {{ capitalizedIncomeClassificationToIncomeAccountMapping.classificationCodeValue.name }}
+ |
+
+
+
+ {{ 'labels.inputs.Income Account' | translate }} |
+
+ ({{ capitalizedIncomeClassificationToIncomeAccountMapping.incomeAccount.glCode }})
+ {{ capitalizedIncomeClassificationToIncomeAccountMapping.incomeAccount.name }}
+ |
+
+
+
+
+
+
diff --git a/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.ts b/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.ts
index b575ff6c1..14e20d492 100644
--- a/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.ts
+++ b/src/app/products/loan-products/common/loan-product-summary/loan-product-summary.component.ts
@@ -1,11 +1,12 @@
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
-import { DelinquencyBucket, LoanProduct } from '../../models/loan-product.model';
+import { AccountingMappingDTO, DelinquencyBucket, LoanProduct } from '../../models/loan-product.model';
import {
AccountingMapping,
Charge,
- ChargeOffReasonCodeValue,
+ CodeValue,
ChargeOffReasonToExpenseAccountMapping,
ChargeToIncomeAccountMapping,
+ ClassificationToIncomeAccountMapping,
GLAccount,
PaymentChannelToFundSourceMapping,
PaymentType,
@@ -114,6 +115,8 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
feeToIncomeAccountMappings: ChargeToIncomeAccountMapping[] = [];
penaltyToIncomeAccountMappings: ChargeToIncomeAccountMapping[] = [];
chargeOffReasonToExpenseAccountMappings: ChargeOffReasonToExpenseAccountMapping[] = [];
+ buydownFeeClassificationToIncomeAccountMappings: ClassificationToIncomeAccountMapping[] = [];
+ capitalizedIncomeClassificationToIncomeAccountMappings: ClassificationToIncomeAccountMapping[] = [];
constructor(private accounting: Accounting) {}
@@ -145,6 +148,10 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
this.feeToIncomeAccountMappings = this.loanProduct.feeToIncomeAccountMappings || [];
this.penaltyToIncomeAccountMappings = this.loanProduct.penaltyToIncomeAccountMappings || [];
this.chargeOffReasonToExpenseAccountMappings = this.loanProduct.chargeOffReasonToExpenseAccountMappings || [];
+ this.buydownFeeClassificationToIncomeAccountMappings =
+ this.loanProduct.buydownFeeClassificationToIncomeAccountMappings || [];
+ this.capitalizedIncomeClassificationToIncomeAccountMappings =
+ this.loanProduct.capitalizedIncomeClassificationToIncomeAccountMappings || [];
} else {
this.accountingMappings = {};
@@ -159,6 +166,9 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
const assetAndLiabilityAccountData =
this.loanProductsTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions || [];
const chargeOffReasonOptions: any = this.loanProductsTemplate.chargeOffReasonOptions || [];
+ const buydownFeeClassificationOptions: any = this.loanProductsTemplate.buydownFeeClassificationOptions || [];
+ const capitalizedIncomeClassificationOptions: any =
+ this.loanProductsTemplate.capitalizedIncomeClassificationOptions || [];
this.accountingMappings = {
fundSourceAccount: this.glAccountLookUp(this.loanProduct.fundSourceAccountId, assetAndLiabilityAccountData),
@@ -262,11 +272,42 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
chargeOffReasonCodeValue: {
id: optionData.id,
name: optionData.value
- } as ChargeOffReasonCodeValue
+ } as CodeValue
});
}
);
}
+
+ this.buydownFeeClassificationToIncomeAccountMappings = [];
+ if (this.loanProduct.buydownFeeClassificationToIncomeAccountMappings?.length > 0) {
+ this.loanProduct.buydownFeeClassificationToIncomeAccountMappings.forEach((m: any) => {
+ let optionData = this.optionDataLookUp(m.classificationCodeValueId, buydownFeeClassificationOptions);
+ if (optionData !== null) {
+ this.buydownFeeClassificationToIncomeAccountMappings.push({
+ incomeAccount: this.glAccountLookUp(m.incomeAccountId, incomeAccountData),
+ classificationCodeValue: {
+ id: optionData.id,
+ name: optionData.value
+ } as CodeValue
+ });
+ }
+ });
+ }
+ this.capitalizedIncomeClassificationToIncomeAccountMappings = [];
+ if (this.loanProduct.capitalizedIncomeClassificationToIncomeAccountMappings?.length > 0) {
+ this.loanProduct.capitalizedIncomeClassificationToIncomeAccountMappings.forEach((m: any) => {
+ let optionData = this.optionDataLookUp(m.classificationCodeValueId, capitalizedIncomeClassificationOptions);
+ if (optionData !== null) {
+ this.capitalizedIncomeClassificationToIncomeAccountMappings.push({
+ incomeAccount: this.glAccountLookUp(m.incomeAccountId, incomeAccountData),
+ classificationCodeValue: {
+ id: optionData.id,
+ name: optionData.value
+ } as CodeValue
+ });
+ }
+ });
+ }
}
if (this.loanProduct.isInterestRecalculationEnabled) {
@@ -453,7 +494,7 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
}
optionDataLookUp(itemId: any, optionsData: any[]): OptionData {
- let optionData: OptionData | null;
+ let optionData: OptionData | null = null;
optionsData.some((o: any) => {
if (o.id === itemId) {
optionData = {
@@ -576,7 +617,9 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
this.loanProduct.paymentChannelToFundSourceMappings?.length > 0 ||
this.loanProduct.feeToIncomeAccountMappings?.length > 0 ||
this.loanProduct.penaltyToIncomeAccountMappings?.length > 0 ||
- this.loanProduct.chargeOffReasonToExpenseAccountMappings?.length > 0
+ this.loanProduct.chargeOffReasonToExpenseAccountMappings?.length > 0 ||
+ this.loanProduct.buydownFeeClassificationToIncomeAccountMappings?.length > 0 ||
+ this.loanProduct.capitalizedIncomeClassificationToIncomeAccountMappings?.length > 0
);
}
diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.html b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.html
new file mode 100644
index 000000000..143322298
--- /dev/null
+++ b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.html
@@ -0,0 +1,40 @@
+
+
+ {{ textHeading | translateKey: 'heading' }}
+
+
+
+
+
+
+
+ | {{ 'labels.inputs.' + textField | translate }} |
+
+ {{ item.value.name }}
+ |
+
+
+
+ {{ 'labels.inputs.GL Account Name or Code' | translate }} |
+ ({{ item.glAccount.glCode }}) {{ item.glAccount.name }} |
+
+
+
+ {{ 'labels.inputs.Actions' | translate }} |
+
+
+
+ |
+
+
+
+
+
+
diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.scss b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.scss
new file mode 100644
index 000000000..d45fe83a7
--- /dev/null
+++ b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.scss
@@ -0,0 +1,12 @@
+table {
+ width: 100%;
+}
+
+.mat-elevation-z1 {
+ margin: 1em 0 1.5em;
+}
+
+h3,
+h4 {
+ font-weight: 500;
+}
diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.ts b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.ts
new file mode 100644
index 000000000..1b4ed9430
--- /dev/null
+++ b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.ts
@@ -0,0 +1,297 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { UntypedFormArray } from '@angular/forms';
+import { MatIconButton } from '@angular/material/button';
+import { MatDialog } from '@angular/material/dialog';
+import {
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ MatTable
+} from '@angular/material/table';
+import { FaIconComponent } from '@fortawesome/angular-fontawesome';
+import { TranslateService } from '@ngx-translate/core';
+import { AccountingMappingDTO, AdvancedMappingDTO } from 'app/products/loan-products/models/loan-product.model';
+import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
+import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
+import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
+import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base';
+import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
+
+@Component({
+ selector: 'mifosx-advanced-accounting-mapping-rule',
+ imports: [
+ ...STANDALONE_SHARED_IMPORTS,
+ FaIconComponent,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCellDef,
+ MatHeaderCell,
+ MatCellDef,
+ MatCell,
+ MatIconButton,
+ MatHeaderRowDef,
+ MatHeaderRow,
+ MatRowDef,
+ MatRow
+ ],
+ templateUrl: './advanced-accounting-mapping-rule.component.html',
+ styleUrl: './advanced-accounting-mapping-rule.component.scss'
+})
+export class AdvancedAccountingMappingRuleComponent implements OnInit {
+ @Input() formType: string;
+ @Input() formArray: UntypedFormArray;
+ @Input() textHeading: string;
+ @Input() textField: string;
+ @Input() allowAddAccountingMapping: boolean = true;
+ @Input() accountingMappingOptions: any[] = [];
+
+ currentFormValues: any[] = [];
+ @Input() chargeData: any;
+ @Input() penaltyData: any;
+ @Input() paymentTypeData: any;
+ @Input() assetAccountData: any;
+ @Input() incomeAccountData: any;
+ @Input() expenseAccountData: any;
+ @Input() liabilityAccountData: any;
+ @Input() incomeAndLiabilityAccountData: any;
+ @Input() assetAndLiabilityAccountData: any;
+
+ @Output() formChangeEvent: EventEmitter
= new EventEmitter();
+
+ tableData: any[] = [];
+
+ tableDisplayedColumns: string[] = [
+ 'codeValueId',
+ 'glAccountId',
+ 'actions'
+ ];
+
+ constructor(
+ public dialog: MatDialog,
+ public translateService: TranslateService
+ ) {}
+
+ ngOnInit(): void {
+ this.tableData = this.formArray?.value || [];
+ this.sendParentData();
+ }
+
+ add() {
+ this.currentFormValues = [];
+ if (this.formType == 'ChargeOffReasonExpense') {
+ this.allowAddAccountingMapping = true;
+ this.tableData.forEach((item: any) => this.currentFormValues.push(item.chargeOffReasonCodeValueId));
+ if (this.accountingMappingOptions.length == this.currentFormValues.length) {
+ this.allowAddAccountingMapping = false;
+ return;
+ }
+ }
+ const data = { ...this.getData(this.formType), pristine: false };
+ const dialogRef = this.dialog.open(FormDialogComponent, { data });
+ dialogRef.afterClosed().subscribe((response: any) => {
+ if (response.data) {
+ const addData: AccountingMappingDTO = {
+ value: this.getValueData(response.data.value.valueId),
+ glAccount: this.getGlAccountData(response.data.value.glAccountId)
+ };
+ this.tableData.push(addData);
+ this.sendParentData();
+
+ if (this.formType == 'ChargeOffReasonExpense') {
+ this.allowAddAccountingMapping = this.tableData.length < this.accountingMappingOptions.length;
+ }
+ }
+ });
+ }
+
+ delete(index: number) {
+ const dialogRef = this.dialog.open(DeleteDialogComponent, {
+ data: { deleteContext: this.translateService.instant('labels.text.this') }
+ });
+ dialogRef.afterClosed().subscribe((response: any) => {
+ if (response.delete) {
+ this.tableData.splice(index, 1);
+ this.sendParentData();
+ }
+ });
+ }
+
+ sendParentData() {
+ const advancedMappingDTO: AdvancedMappingDTO = {
+ formType: this.formType,
+ values: this.tableData
+ };
+ this.formChangeEvent.emit(advancedMappingDTO);
+ }
+
+ getData(formType: string, values?: any) {
+ switch (formType) {
+ case 'PaymentFundSource':
+ return {
+ title: 'Configure Fund Sources for Payment Channels',
+ formfields: this.getPaymentFundSourceFormfields(values)
+ };
+ case 'FeesIncome':
+ return { title: 'Map Fees to Income Accounts', formfields: this.getFeesIncomeFormfields(values) };
+ case 'PenaltyIncome':
+ return {
+ title: 'Map Penalties to Specific Income Accounts',
+ formfields: this.getPenaltyIncomeFormfields(values)
+ };
+ case 'ChargeOffReasonExpense':
+ return {
+ title: 'Map Charge-off reasons to Expense accounts',
+ formfields: this.getChargeOffReasonExpenseFormfields(values)
+ };
+ case 'BuydownFeeClassificationToIncome':
+ return {
+ title: 'Buydown Fee classifications to Income accounts',
+ formfields: this.getClassificationIncomeFormfields(values)
+ };
+ case 'CapitalizedIncomeClassificationToIncome':
+ return {
+ title: 'Capitalized Income classifications to Income accounts',
+ formfields: this.getClassificationIncomeFormfields(values)
+ };
+ }
+ }
+
+ getPaymentFundSourceFormfields(values?: any) {
+ const formfields: FormfieldBase[] = [
+ new SelectBase({
+ controlName: 'paymentTypeId',
+ label: 'Payment Type',
+ value: values ? values.paymentTypeId : this.paymentTypeData[0].id,
+ options: { label: 'name', value: 'id', data: this.paymentTypeData },
+ required: true,
+ order: 1
+ }),
+ new SelectBase({
+ controlName: 'fundSourceAccountId',
+ label: 'Fund Source',
+ value: values ? values.fundSourceAccountId : this.assetAccountData[0].id,
+ options: { label: 'name', value: 'id', data: this.assetAccountData },
+ required: true,
+ order: 2
+ })
+
+ ];
+ return formfields;
+ }
+
+ getFeesIncomeFormfields(values?: any) {
+ const formfields: FormfieldBase[] = [
+ new SelectBase({
+ controlName: 'chargeId',
+ label: 'Fees',
+ value: values ? values.chargeId : this.chargeData[0].id,
+ options: { label: 'name', value: 'id', data: this.chargeData },
+ required: true,
+ order: 1
+ }),
+ new SelectBase({
+ controlName: 'incomeAccountId',
+ label: 'Income Account',
+ value: values ? values.incomeAccountId : this.incomeAndLiabilityAccountData[0].id,
+ options: { label: 'name', value: 'id', data: this.incomeAndLiabilityAccountData },
+ required: true,
+ order: 2
+ })
+
+ ];
+ return formfields;
+ }
+
+ getPenaltyIncomeFormfields(values?: any) {
+ const formfields: FormfieldBase[] = [
+ new SelectBase({
+ controlName: 'chargeId',
+ label: 'Penalty',
+ value: values ? values.chargeId : this.penaltyData[0].id,
+ options: { label: 'name', value: 'id', data: this.penaltyData },
+ required: true,
+ order: 1
+ }),
+ new SelectBase({
+ controlName: 'incomeAccountId',
+ label: 'Income Account',
+ value: values ? values.incomeAccountId : this.incomeAccountData[0].id,
+ options: { label: 'name', value: 'id', data: this.incomeAccountData },
+ required: true,
+ order: 2
+ })
+
+ ];
+ return formfields;
+ }
+
+ getChargeOffReasonExpenseFormfields(values?: any) {
+ const reasonOptions = this.accountingMappingOptions.filter(
+ (item: any) => !this.currentFormValues.includes(item.id)
+ );
+ const formfields: FormfieldBase[] = [
+ new SelectBase({
+ controlName: 'chargeOffReasonCodeValueId',
+ label: 'Charge-off reason',
+ value: values ? values.chargeOffReasonCodeValueId : reasonOptions[0].id,
+ options: { label: 'name', value: 'id', data: reasonOptions },
+ required: true,
+ order: 1
+ }),
+ new SelectBase({
+ controlName: 'expenseAccountId',
+ label: 'Expense Account',
+ value: values ? values.expenseAccountId : this.expenseAccountData[0].id,
+ options: { label: 'name', value: 'id', data: this.expenseAccountData },
+ required: true,
+ order: 2
+ })
+
+ ];
+ return formfields;
+ }
+
+ getClassificationIncomeFormfields(values?: any) {
+ const classificationOptions = this.accountingMappingOptions.filter(
+ (item: any) => !this.currentFormValues.includes(item.id)
+ );
+ const formfields: FormfieldBase[] = [
+ new SelectBase({
+ controlName: 'valueId',
+ label: 'Classification',
+ value: values ? values.chargeOffReasonCodeValueId : classificationOptions[0].id,
+ options: { label: 'name', value: 'id', data: classificationOptions },
+ required: true,
+ order: 1
+ }),
+ new SelectBase({
+ controlName: 'glAccountId',
+ label: 'Income Account',
+ value: values ? values.incomeAccountId : this.incomeAccountData[0].id,
+ options: { label: 'name', value: 'id', data: this.incomeAccountData },
+ required: true,
+ order: 2
+ })
+
+ ];
+ return formfields;
+ }
+
+ getValueData(valueId: number): any {
+ return this.accountingMappingOptions.find((i: any) => {
+ return i.id === valueId;
+ });
+ }
+
+ getGlAccountData(valueId: number): any {
+ return this.incomeAccountData.find((i: any) => {
+ return i.id === valueId;
+ });
+ }
+}
diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.html b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.html
index 3dcc1f891..94095ebb8 100644
--- a/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.html
+++ b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.html
@@ -514,6 +514,28 @@
+
+
+
+
diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts
index 3e973eecd..ce02cd832 100644
--- a/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts
+++ b/src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts
@@ -8,7 +8,10 @@ import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.componen
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 {
+ ChargeOffReasonToExpenseAccountMapping,
+ ClassificationToIncomeAccountMapping
+} from 'app/shared/models/general.model';
import { DeferredIncomeRecognition } from '../loan-product-payment-strategy-step/payment-allocation-model';
import { MatRadioGroup, MatRadioButton } from '@angular/material/radio';
import { MatDivider } from '@angular/material/divider';
@@ -31,6 +34,8 @@ import {
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
import { FindPipe } from '../../../../pipes/find.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
+import { AdvancedAccountingMappingRuleComponent } from './advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component';
+import { AccountingMappingDTO, AdvancedMappingDTO } from '../../models/loan-product.model';
@Component({
selector: 'mifosx-loan-product-accounting-step',
@@ -57,7 +62,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatRow,
MatStepperPrevious,
MatStepperNext,
- FindPipe
+ FindPipe,
+ AdvancedAccountingMappingRuleComponent
]
})
export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
@@ -78,6 +84,8 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
incomeAndLiabilityAccountData: any;
assetAndLiabilityAccountData: any;
chargeOffReasonOptions: any;
+ capitalizedIncomeClassificationOptions: any[] = [];
+ buydownFeeClassificationOptions: any[] = [];
currentFormValues: any[] = [];
allowAddChargeOffReasonExpense = true;
@@ -123,6 +131,9 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
this.assetAndLiabilityAccountData =
this.loanProductsTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions || [];
this.chargeOffReasonOptions = this.loanProductsTemplate.chargeOffReasonOptions || [];
+ this.capitalizedIncomeClassificationOptions =
+ this.loanProductsTemplate.capitalizedIncomeClassificationOptions || [];
+ this.buydownFeeClassificationOptions = this.loanProductsTemplate.buydownFeeClassificationOptions || [];
this.loanProductAccountingForm.patchValue({
accountingRule: this.loanProductsTemplate.accountingRule.id
@@ -201,7 +212,9 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
this.loanProductsTemplate.paymentChannelToFundSourceMappings ||
this.loanProductsTemplate.feeToIncomeAccountMappings ||
this.loanProductsTemplate.penaltyToIncomeAccountMappings ||
- this.loanProductsTemplate.chargeOffReasonToExpenseAccountMappings
+ this.loanProductsTemplate.chargeOffReasonToExpenseAccountMappings ||
+ this.loanProductsTemplate.buydownFeeClassificationToIncomeAccountMappings ||
+ this.loanProductsTemplate.capitalizedIncomeClassificationToIncomeAccountMappings
? true
: false
});
@@ -244,6 +257,28 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
)
)
);
+ this.loanProductAccountingForm.setControl(
+ 'buydownfeeClassificationToIncomeAccountMappings',
+ this.formBuilder.array(
+ (this.loanProductsTemplate.buydownFeeClassificationToIncomeAccountMappings || []).map(
+ (m: ClassificationToIncomeAccountMapping) => ({
+ value: m.classificationCodeValue,
+ glAccount: m.incomeAccount
+ })
+ )
+ )
+ );
+ this.loanProductAccountingForm.setControl(
+ 'capitalizedIncomeClassificationToIncomeAccountMappings',
+ this.formBuilder.array(
+ (this.loanProductsTemplate.capitalizedIncomeClassificationToIncomeAccountMappings || []).map(
+ (m: ClassificationToIncomeAccountMapping) => ({
+ value: m.classificationCodeValue,
+ glAccount: m.incomeAccount
+ })
+ )
+ )
+ );
}
}
@@ -341,6 +376,14 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
'chargeOffReasonToExpenseAccountMappings',
this.formBuilder.array([])
);
+ this.loanProductAccountingForm.addControl(
+ 'buydownfeeClassificationToIncomeAccountMappings',
+ this.formBuilder.array([])
+ );
+ this.loanProductAccountingForm.addControl(
+ 'capitalizedIncomeClassificationToIncomeAccountMappings',
+ this.formBuilder.array([])
+ );
} else {
this.loanProductAccountingForm.setControl(
'paymentChannelToFundSourceMappings',
@@ -352,6 +395,14 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
'chargeOffReasonToExpenseAccountMappings',
this.formBuilder.array([])
);
+ this.loanProductAccountingForm.setControl(
+ 'buydownfeeClassificationToIncomeAccountMappings',
+ this.formBuilder.array([])
+ );
+ this.loanProductAccountingForm.setControl(
+ 'capitalizedIncomeClassificationToIncomeAccountMappings',
+ this.formBuilder.array([])
+ );
}
});
} else {
@@ -415,6 +466,16 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
return this.loanProductAccountingForm.get('chargeOffReasonToExpenseAccountMappings') as UntypedFormArray;
}
+ get buydownfeeClassificationToIncomeAccountMappings(): UntypedFormArray {
+ return this.loanProductAccountingForm.get('buydownfeeClassificationToIncomeAccountMappings') as UntypedFormArray;
+ }
+
+ get capitalizedIncomeClassificationToIncomeAccountMappings(): UntypedFormArray {
+ return this.loanProductAccountingForm.get(
+ 'capitalizedIncomeClassificationToIncomeAccountMappings'
+ ) as UntypedFormArray;
+ }
+
setLoanProductAccountingFormDirty() {
if (this.loanProductAccountingForm.pristine) {
this.loanProductAccountingForm.markAsDirty();
@@ -635,4 +696,31 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
}
}
}
+
+ formChangeEvent(accountingData: AdvancedMappingDTO) {
+ if (accountingData.formType === 'BuydownFeeClassificationToIncome') {
+ this.loanProductAccountingForm.setControl(
+ 'buydownfeeClassificationToIncomeAccountMappings',
+ this.formBuilder.array(
+ (accountingData.values || []).map((m: AccountingMappingDTO) => ({
+ classificationCodeValueId: m.value.id,
+ incomeAccountId: m.glAccount.id
+ }))
+ )
+ );
+ console.log(this.loanProductAccountingForm.value.buydownfeeClassificationToIncomeAccountMappings);
+ } else if (accountingData.formType === 'CapitalizedIncomeClassificationToIncome') {
+ this.loanProductAccountingForm.setControl(
+ 'capitalizedIncomeClassificationToIncomeAccountMappings',
+ this.formBuilder.array(
+ (accountingData.values || []).map((m: AccountingMappingDTO) => ({
+ classificationCodeValueId: m.value.id,
+ incomeAccountId: m.glAccount.id
+ }))
+ )
+ );
+ console.log(this.loanProductAccountingForm.value.capitalizedIncomeClassificationToIncomeAccountMappings);
+ }
+ this.setLoanProductAccountingFormDirty();
+ }
}
diff --git a/src/app/products/loan-products/models/loan-product.model.ts b/src/app/products/loan-products/models/loan-product.model.ts
index d4a6a434f..30f28496f 100644
--- a/src/app/products/loan-products/models/loan-product.model.ts
+++ b/src/app/products/loan-products/models/loan-product.model.ts
@@ -2,7 +2,10 @@ import {
AccountingMapping,
ChargeOffReasonToExpenseAccountMapping,
ChargeToIncomeAccountMapping,
+ ClassificationToIncomeAccountMapping,
+ CodeValue,
Currency,
+ GLAccount,
PaymentChannelToFundSourceMapping
} from 'app/shared/models/general.model';
import { OptionData, StringEnumOptionData } from 'app/shared/models/option-data.model';
@@ -152,6 +155,8 @@ export interface LoanProduct {
enableAccrualActivityPosting?: boolean;
supportedInterestRefundTypes?: StringEnumOptionData[];
chargeOffBehaviour?: StringEnumOptionData;
+ buydownFeeClassificationToIncomeAccountMappings?: ClassificationToIncomeAccountMapping[];
+ capitalizedIncomeClassificationToIncomeAccountMappings?: ClassificationToIncomeAccountMapping[];
}
export interface AllowAttributeOverrides {
@@ -193,3 +198,13 @@ export interface InterestRecalculationData {
allowCompoundingOnEod: boolean;
disallowInterestCalculationOnPastDue: boolean;
}
+
+export interface AdvancedMappingDTO {
+ formType: string;
+ values: AccountingMappingDTO[];
+}
+
+export interface AccountingMappingDTO {
+ value: CodeValue;
+ glAccount: GLAccount;
+}
diff --git a/src/app/products/products.module.ts b/src/app/products/products.module.ts
index b8701b661..8ef155bee 100644
--- a/src/app/products/products.module.ts
+++ b/src/app/products/products.module.ts
@@ -122,6 +122,7 @@ import { ViewAdvancePaymenyAllocationComponent } from './loan-products/view-loan
import { AdvancePaymentAllocationTabComponent } from './loan-products/loan-product-stepper/loan-product-payment-strategy-step/advance-payment-allocation-tab/advance-payment-allocation-tab.component';
import { LoanProductSummaryComponent } from './loan-products/common/loan-product-summary/loan-product-summary.component';
import { LoanProductDeferredIncomeRecognitionStepComponent } from './loan-products/loan-product-stepper/loan-product-capitalized-income-step/loan-product-deferred-income-recognition-step.component';
+import { AdvancedAccountingMappingRuleComponent } from './loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component';
/**
* Products Module
@@ -249,7 +250,8 @@ import { LoanProductDeferredIncomeRecognitionStepComponent } from './loan-produc
ViewAdvancePaymenyAllocationComponent,
AdvancePaymentAllocationTabComponent,
LoanProductSummaryComponent,
- LoanProductDeferredIncomeRecognitionStepComponent
+ LoanProductDeferredIncomeRecognitionStepComponent,
+ AdvancedAccountingMappingRuleComponent
]
})
export class ProductsModule {}
diff --git a/src/app/shared/models/general.model.ts b/src/app/shared/models/general.model.ts
index 13c04c983..dea5fdecd 100644
--- a/src/app/shared/models/general.model.ts
+++ b/src/app/shared/models/general.model.ts
@@ -42,11 +42,25 @@ export interface PaymentChannelToFundSourceMapping {
export interface ChargeOffReasonToExpenseAccountMapping {
chargeOffReasonCodeValueId?: number;
expenseAccountId?: number;
- chargeOffReasonCodeValue?: ChargeOffReasonCodeValue;
+ chargeOffReasonCodeValue?: CodeValue;
expenseAccount?: AccountingMapping;
}
-export interface ChargeOffReasonCodeValue {
+export interface AccountMapping {
+ codeValueId?: number;
+ glAccountId?: number;
+ codeValue?: CodeValue;
+ glAccount?: AccountingMapping;
+}
+
+export interface ClassificationToIncomeAccountMapping {
+ classificationCodeValueId?: number;
+ incomeAccountId?: number;
+ classificationCodeValue?: CodeValue;
+ incomeAccount?: AccountingMapping;
+}
+
+export interface CodeValue {
active: boolean;
description: string;
id: number;
diff --git a/src/app/system/manage-jobs/scheduler-jobs/custom-parameters-popover/custom-parameters-popover.component.ts b/src/app/system/manage-jobs/scheduler-jobs/custom-parameters-popover/custom-parameters-popover.component.ts
index 01b3e1b16..e0a4e4cc2 100644
--- a/src/app/system/manage-jobs/scheduler-jobs/custom-parameters-popover/custom-parameters-popover.component.ts
+++ b/src/app/system/manage-jobs/scheduler-jobs/custom-parameters-popover/custom-parameters-popover.component.ts
@@ -10,7 +10,7 @@ import {
import { CustomParametersTableComponent } from './custom-parameters-table/custom-parameters-table.component';
import { SystemService } from 'app/system/system.service';
import { CdkScrollable } from '@angular/cdk/scrolling';
-import { NgFor, NgClass } from '@angular/common';
+import { NgClass } from '@angular/common';
import { MatList, MatListItem } from '@angular/material/list';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
diff --git a/src/assets/translations/cs-CS.json b/src/assets/translations/cs-CS.json
index 72c0e4290..fc8cb5fc7 100644
--- a/src/assets/translations/cs-CS.json
+++ b/src/assets/translations/cs-CS.json
@@ -839,6 +839,8 @@
"Bulk Import": "Hromadný import",
"Bulk Loan Reassignment": "Hromadné přeřazení půjčky",
"Business Rule Parameters": "Parametry obchodních pravidel",
+ "Buydown Fee classifications to Income accounts": "Klasifikace poplatků za odkup na příjmové účty",
+ "Capitalized Income classifications to Income accounts": "Klasifikace kapitalizovaných výnosů do výnosových účtů",
"COB Catch-Up is": "COB Catch-Up je",
"Calculate Interest": "Vypočítejte úrok",
"Campaign Message": "Zpráva kampaně",
diff --git a/src/assets/translations/de-DE.json b/src/assets/translations/de-DE.json
index e3528ac01..d26202f54 100644
--- a/src/assets/translations/de-DE.json
+++ b/src/assets/translations/de-DE.json
@@ -840,6 +840,8 @@
"Bulk Import": "Massenimport",
"Bulk Loan Reassignment": "Neuzuweisung von Massenkrediten",
"Business Rule Parameters": "Geschäftsregelparameter",
+ "Buydown Fee classifications to Income accounts": "Buydown-Gebührenklassifizierungen für Einkommenskonten",
+ "Capitalized Income classifications to Income accounts": "Klassifizierung kapitalisierter Einkünfte in Einkommenskonten",
"COB Catch-Up is": "COB Catch-Up ist",
"Calculate Interest": "Zinsen berechnen",
"Campaign Message": "Kampagnenbotschaft",
diff --git a/src/assets/translations/en-US.json b/src/assets/translations/en-US.json
index 2d0a67cbf..6ad10cb72 100644
--- a/src/assets/translations/en-US.json
+++ b/src/assets/translations/en-US.json
@@ -845,6 +845,8 @@
"Bulk Import": "Bulk Import",
"Bulk Loan Reassignment": "Bulk Loan Reassignment",
"Business Rule Parameters": "Business Rule Parameters",
+ "Buydown Fee classifications to Income accounts": "Buydown Fee classifications to Income accounts",
+ "Capitalized Income classifications to Income accounts": "Capitalized Income classifications to Income accounts",
"COB Catch-Up is": "COB Catch-Up is",
"Calculate Interest": "Calculate Interest",
"Campaign Message": "Campaign Message",
diff --git a/src/assets/translations/es-CL.json b/src/assets/translations/es-CL.json
index 57a7c4400..23e5a45d4 100644
--- a/src/assets/translations/es-CL.json
+++ b/src/assets/translations/es-CL.json
@@ -839,6 +839,8 @@
"Bulk Import": "Importación masiva",
"Bulk Loan Reassignment": "Reasignación de Créditos másiva",
"Business Rule Parameters": "Parámetros de reglas de negocio",
+ "Buydown Fee classifications to Income accounts": "Clasificaciones de comisiones por reducción de precio en cuentas de ingresos",
+ "Capitalized Income classifications to Income accounts": "Clasificaciones de ingresos capitalizados a cuentas de ingresos",
"COB Catch-Up is": "La puesta al día de COB es",
"Calculate Interest": "Calcular interés",
"Campaign Message": "Mensaje de campaña",
diff --git a/src/assets/translations/es-MX.json b/src/assets/translations/es-MX.json
index 740290fe6..e16294c18 100644
--- a/src/assets/translations/es-MX.json
+++ b/src/assets/translations/es-MX.json
@@ -839,6 +839,8 @@
"Bulk Import": "Importación masiva",
"Bulk Loan Reassignment": "Reasignación de Créditos másiva",
"Business Rule Parameters": "Parámetros de reglas de negocio",
+ "Buydown Fee classifications to Income accounts": "Clasificaciones de comisiones por reducción de precio en cuentas de ingresos",
+ "Capitalized Income classifications to Income accounts": "Clasificaciones de ingresos capitalizados a cuentas de ingresos",
"COB Catch-Up is": "La puesta al día de COB es",
"Calculate Interest": "Calcular interés",
"Campaign Message": "Mensaje de campaña",
diff --git a/src/assets/translations/fr-FR.json b/src/assets/translations/fr-FR.json
index fb6c19b5a..4fa9aea5c 100644
--- a/src/assets/translations/fr-FR.json
+++ b/src/assets/translations/fr-FR.json
@@ -840,6 +840,8 @@
"Bulk Import": "Importation en masse",
"Bulk Loan Reassignment": "Réaffectation groupée de prêts",
"Business Rule Parameters": "Paramètres des règles métier",
+ "Buydown Fee classifications to Income accounts": "Classification des frais de rachat dans les comptes de revenus",
+ "Capitalized Income classifications to Income accounts": "Classifications des revenus capitalisés vers les comptes de revenus",
"COB Catch-Up is": "Le rattrapage COB est",
"Calculate Interest": "Calculer les intérêts",
"Campaign Message": "Message de campagne",
diff --git a/src/assets/translations/it-IT.json b/src/assets/translations/it-IT.json
index bacccad23..ec2828e96 100644
--- a/src/assets/translations/it-IT.json
+++ b/src/assets/translations/it-IT.json
@@ -840,6 +840,8 @@
"Bulk Import": "Importazione in blocco",
"Bulk Loan Reassignment": "Riassegnazione del prestito in blocco",
"Business Rule Parameters": "Parametri delle regole aziendali",
+ "Buydown Fee classifications to Income accounts": "Classificazioni delle commissioni di riacquisto nei conti di reddito",
+ "Capitalized Income classifications to Income accounts": "Classificazioni del reddito capitalizzato nei conti di reddito",
"COB Catch-Up is": "Il recupero del COB lo è",
"Calculate Interest": "Calcola gli interessi",
"Campaign Message": "Messaggio della campagna",
diff --git a/src/assets/translations/ko-KO.json b/src/assets/translations/ko-KO.json
index 3fd4126be..d1d40d7da 100644
--- a/src/assets/translations/ko-KO.json
+++ b/src/assets/translations/ko-KO.json
@@ -840,6 +840,8 @@
"Bulk Import": "대량 가져오기",
"Bulk Loan Reassignment": "대량대출 재할당",
"Business Rule Parameters": "비즈니스 규칙 매개변수",
+ "Buydown Fee classifications to Income accounts": "소득 계정에 대한 Buydown 수수료 분류",
+ "Capitalized Income classifications to Income accounts": "자본화된 소득 분류를 소득 계정으로",
"COB Catch-Up is": "COB 따라잡기는",
"Calculate Interest": "이자 계산",
"Campaign Message": "캠페인 메시지",
diff --git a/src/assets/translations/lt-LT.json b/src/assets/translations/lt-LT.json
index 28b139838..a2a83f51e 100644
--- a/src/assets/translations/lt-LT.json
+++ b/src/assets/translations/lt-LT.json
@@ -840,6 +840,8 @@
"Bulk Import": "Masinis importas",
"Bulk Loan Reassignment": "Masinės paskolos perskirstymas",
"Business Rule Parameters": "Verslo taisyklių parametrai",
+ "Buydown Fee classifications to Income accounts": "Išpirkimo mokesčių klasifikavimas į pajamų sąskaitas",
+ "Capitalized Income classifications to Income accounts": "Kapitalizuotų pajamų klasifikavimas į pajamų sąskaitas",
"COB Catch-Up is": "COB Catch-Up yra",
"Calculate Interest": "Apskaičiuokite palūkanas",
"Campaign Message": "Kampanijos pranešimas",
diff --git a/src/assets/translations/lv-LV.json b/src/assets/translations/lv-LV.json
index 1c4c9d794..7f92c8283 100644
--- a/src/assets/translations/lv-LV.json
+++ b/src/assets/translations/lv-LV.json
@@ -840,6 +840,8 @@
"Bulk Import": "Lielapjoma importēšana",
"Bulk Loan Reassignment": "Lielapjoma aizdevuma pārcelšana",
"Business Rule Parameters": "Biznesa noteikumu parametri",
+ "Buydown Fee classifications to Income accounts": "Izpirkšanas maksu klasifikācija ienākumu kontos",
+ "Capitalized Income classifications to Income accounts": "Kapitalizēto ienākumu klasifikācija ienākumu kontos",
"COB Catch-Up is": "COB Catch-Up ir",
"Calculate Interest": "Aprēķināt procentus",
"Campaign Message": "Kampaņas ziņojums",
diff --git a/src/assets/translations/ne-NE.json b/src/assets/translations/ne-NE.json
index e844022f6..808c48152 100644
--- a/src/assets/translations/ne-NE.json
+++ b/src/assets/translations/ne-NE.json
@@ -840,6 +840,8 @@
"Bulk Import": "थोक आयात",
"Bulk Loan Reassignment": "बल्क ऋण पुन: असाइनमेन्ट",
"Business Rule Parameters": "व्यापार नियम प्यारामिटरहरू",
+ "Buydown Fee classifications to Income accounts": "आय खाताहरूमा खरिद शुल्क वर्गीकरण",
+ "Capitalized Income classifications to Income accounts": "आय खाताहरूमा पूंजीकृत आय वर्गीकरण",
"COB Catch-Up is": "COB क्याच-अप हो",
"Calculate Interest": "ब्याज गणना गर्नुहोस्",
"Campaign Message": "अभियान सन्देश",
diff --git a/src/assets/translations/pt-PT.json b/src/assets/translations/pt-PT.json
index 4a5983dd3..7d4fb4378 100644
--- a/src/assets/translations/pt-PT.json
+++ b/src/assets/translations/pt-PT.json
@@ -840,6 +840,8 @@
"Bulk Import": "Importação em massa",
"Bulk Loan Reassignment": "Reatribuição de empréstimo em massa",
"Business Rule Parameters": "Parâmetros de regras de negócios",
+ "Buydown Fee classifications to Income accounts": "Classificações de taxas de recompra para contas de renda",
+ "Capitalized Income classifications to Income accounts": "Classificações de renda capitalizada para contas de renda",
"COB Catch-Up is": "A recuperação do COB é",
"Calculate Interest": "Calcular juros",
"Campaign Message": "Mensagem da campanha",
diff --git a/src/assets/translations/sw-SW.json b/src/assets/translations/sw-SW.json
index 581362f58..7b0d7e32d 100644
--- a/src/assets/translations/sw-SW.json
+++ b/src/assets/translations/sw-SW.json
@@ -840,6 +840,8 @@
"Bulk Import": "Ingiza Wingi",
"Bulk Loan Reassignment": "Ugawaji upya wa mkopo kwa wingi",
"Business Rule Parameters": "Vigezo vya Sheria ya Biashara",
+ "Buydown Fee classifications to Income accounts": "Uainishaji wa Ada ya Kununua kwa akaunti za Mapato",
+ "Capitalized Income classifications to Income accounts": "Uainishaji wa Mapato ya Mtaji kwa akaunti za Mapato",
"COB Catch-Up is": "COB Catch-Up ni",
"Calculate Interest": "Hesabu Riba",
"Campaign Message": "Ujumbe wa Kampeni",