This commit is contained in:
Jose Alberto Hernandez 2026-02-05 17:44:37 -05:00 committed by GitHub
commit 2737212180
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 1360 additions and 30 deletions

View File

@ -15,6 +15,7 @@ import { Observable } from 'rxjs';
/** Custom Services */
import { LoansService } from '../loans.service';
import { OrganizationService } from 'app/organization/organization.service';
/**
* Loans notes data resolver.
@ -22,6 +23,7 @@ import { LoansService } from '../loans.service';
@Injectable()
export class LoanActionButtonResolver {
private loansService = inject(LoansService);
private organizationService = inject(OrganizationService);
/**
* Returns the Loans Notes Data.
@ -88,6 +90,8 @@ export class LoanActionButtonResolver {
return this.loansService.getLoanActionTemplate(loanId, 'reAge');
} else if (loanActionButton === 'Re-Amortize') {
return this.loansService.getLoanActionTemplate(loanId, 'reAmortization');
} else if (loanActionButton === 'Attach Loan Originator') {
return this.organizationService.getLoanOriginators();
} else {
return undefined;
}

View File

@ -56,17 +56,6 @@
<input matInput [value]="loanData.availableDisbursementAmountWithOverApplied | formatNumber" readonly />
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Transaction Amount' | translate }}</mat-label>
<input matInput type="number" required formControlName="approvedLoanAmount" />
@if (approveLoanForm.controls.approvedLoanAmount.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Transaction Amount' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>

View File

@ -0,0 +1,42 @@
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="container mat-elevation-z8">
<mat-card>
<form [formGroup]="attachLoanOriginatorForm" (ngSubmit)="submit()">
<mat-card-content>
<div class="layout-column">
<mat-form-field>
<mat-label>{{ 'labels.inputs.Loan Originator' | translate }}</mat-label>
<mat-select formControlName="originatorId">
@for (loanOriginator of loanOriginators; track loanOriginator) {
<mat-option [value]="loanOriginator.id">
{{ loanOriginator.name }}
</mat-option>
}
</mat-select>
</mat-form-field>
</div>
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
<button type="button" mat-raised-button [routerLink]="['../../general']">
{{ 'labels.buttons.Cancel' | translate }}
</button>
<button
mat-raised-button
color="primary"
[disabled]="!attachLoanOriginatorForm.valid"
*mifosxHasPermission="'ATTACH_LOAN_ORIGINATOR'"
>
{{ 'labels.buttons.Submit' | translate }}
</button>
</mat-card-actions>
</mat-card-content>
</form>
</mat-card>
</div>

View File

@ -0,0 +1,11 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
.container {
max-width: 37rem;
}

View File

@ -0,0 +1,81 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports. */
import { Component, Input, OnInit, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Services. */
import { LoansService } from 'app/loans/loans.service';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { LoanOriginator } from 'app/loans/models/loan-account.model';
/**
* Attach Loan Originator component.
*/
@Component({
selector: 'mifosx-attach-originator',
templateUrl: './attach-originator.component.html',
styleUrl: './attach-originator.component.scss',
imports: [
...STANDALONE_SHARED_IMPORTS
]
})
export class AttachOriginatorComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private route = inject(ActivatedRoute);
private loanService = inject(LoansService);
private router = inject(Router);
/** Attach Loan Originator Loan form. */
attachLoanOriginatorForm: UntypedFormGroup;
/** Loan data. */
loanOriginators: LoanOriginator[] = [];
@Input() dataObject: any;
/** Loan Id */
loanId: string | null = null;
constructor() {
this.loanId = this.route.snapshot.params['loanId'];
}
ngOnInit() {
this.setAttachLoanOriginatorForm();
console.log(this.dataObject);
this.loanOriginators = [];
this.dataObject.forEach((loanOriginator: LoanOriginator) => {
if (loanOriginator.status === 'ACTIVE') {
this.loanOriginators.push(loanOriginator);
}
});
}
/**
* Set Attach Loan Originator form.
*/
setAttachLoanOriginatorForm() {
this.attachLoanOriginatorForm = this.formBuilder.group({
originatorId: [
'',
Validators.required
]
});
}
/**
* Submits Approve form.
*/
submit() {
const approveLoanFormData = this.attachLoanOriginatorForm.value;
this.loanService.attachLoanOriginator(this.loanId, approveLoanFormData.originatorId).subscribe((response: any) => {
this.router.navigate(['../../general'], { relativeTo: this.route });
});
}
}

View File

@ -114,3 +114,6 @@
@if (actions['Undo Write-off']) {
<mifosx-undo-write-off [dataObject]="actionButtonData"></mifosx-undo-write-off>
}
@if (actions['Attach Loan Originator']) {
<mifosx-attach-originator [dataObject]="actionButtonData"></mifosx-attach-originator>
}

View File

@ -40,6 +40,7 @@ import { LoanReamortizeComponent } from './loan-reamortize/loan-reamortize.compo
import { AddInterestPauseComponent } from './add-interest-pause/add-interest-pause.component';
import { UndoWriteOffComponent } from './undo-write-off/undo-write-off.component';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { AttachOriginatorComponent } from './attach-originator/attach-originator.component';
/**
* Loan Account Actions component.
@ -79,7 +80,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
LoanReagingComponent,
LoanReamortizeComponent,
AddInterestPauseComponent,
UndoWriteOffComponent
UndoWriteOffComponent,
AttachOriginatorComponent
]
})
export class LoanAccountActionsComponent {
@ -130,6 +132,7 @@ export class LoanAccountActionsComponent {
'Contract Termination': boolean;
'Buy Down Fee': boolean;
'Undo Write-off': boolean;
'Attach Loan Originator': boolean;
} = {
Close: false,
'Undo Approval': false,
@ -169,7 +172,8 @@ export class LoanAccountActionsComponent {
'Capitalized Income': false,
'Contract Termination': false,
'Buy Down Fee': false,
'Undo Write-off': false
'Undo Write-off': false,
'Attach Loan Originator': false
};
actionButtonData: any;

View File

@ -90,6 +90,11 @@ export class LoansAccountButtonConfiguration {
name: 'Reject',
icon: 'times',
taskPermissionName: 'REJECT_LOAN'
},
{
name: 'Attach Loan Originator',
icon: 'edit',
taskPermissionName: 'ATTACH_LOAN_ORIGINATOR'
}
];
break;

View File

@ -34,16 +34,35 @@
{{ item.status }}
</td>
</ng-container>
<ng-container matColumnDef="originatorTypeId">
<ng-container matColumnDef="originatorType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Originator Type' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.originatorTypeId }}
{{ item.originatorType.name }}
</td>
</ng-container>
<ng-container matColumnDef="channelTypeId">
<ng-container matColumnDef="channelType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Channel Type' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.channelTypeId }}
{{ item.channelType.name }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">
@if (loanStatus.pendingApproval) {
<button
type="button"
color="warn"
title="{{ 'tooltips.Dettach' | translate }}"
mat-icon-button
matTooltip="{{ 'tooltips.Delete' | translate }}"
*mifosxHasPermission="'DETTACH_LOAN_ORIGINATOR'"
matTooltipPosition="above"
(click)="dettachLoanOriginator(loanOriginator)"
>
<fa-icon icon="trash" size="lg"></fa-icon>
</button>
}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="loanoriginatorsColumns"></tr>

View File

@ -6,6 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Component, inject } from '@angular/core';
import { MatIconButton } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import {
MatCell,
MatCellDef,
@ -18,8 +20,13 @@ import {
MatRowDef,
MatTable
} from '@angular/material/table';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { TranslateService } from '@ngx-translate/core';
import { LoansService } from 'app/loans/loans.service';
import { LoanOriginator } from 'app/loans/models/loan-account.model';
import { LoanStatus } from 'app/loans/models/loan-status.model';
import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@Component({
@ -37,29 +44,73 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatHeaderRowDef,
MatHeaderRow,
MatRowDef,
MatRow
MatRow,
MatIconButton,
FaIconComponent
]
})
export class LoanOriginatorsTabComponent {
private route = inject(ActivatedRoute);
private router = inject(Router);
private loansService = inject(LoansService);
private translateService = inject(TranslateService);
private dialog = inject(MatDialog);
loanOriginatorsData: LoanOriginator[] = [];
loanId: number | null = null;
loanId: string | null = null;
clientId: string | null = null;
loanStatus: LoanStatus | null = null;
loanoriginatorsColumns: string[] = [
'id',
'externalId',
'name',
'status',
'originatorTypeId',
'channelTypeId'
'originatorType',
'channelType',
'actions'
];
constructor() {
const loanIdParam = this.route.parent?.parent?.snapshot.paramMap.get('loanId');
this.loanId = loanIdParam ? Number(loanIdParam) : null;
this.clientId = this.route.parent.parent.snapshot.paramMap.get('clientId');
this.loanId = this.route.parent?.parent?.snapshot.paramMap.get('loanId');
this.route.parent.parent.data.subscribe((data: { loanDetailsData: any }) => {
this.loanStatus = data.loanDetailsData.status;
});
this.route.parent.data.subscribe((data: { loanOriginatorsData: any }) => {
this.loanOriginatorsData = data.loanOriginatorsData.originators;
});
}
dettachLoanOriginator(loanOriginator: LoanOriginator): void {
const dettachCodeDialogRef = this.dialog.open(ConfirmationDialogComponent, {
data: {
heading: this.translateService.instant('labels.heading.Loan Originators'),
dialogContext:
this.translateService.instant('labels.buttons.Delete') +
' ' +
this.translateService.instant('labels.inputs.Loan Originator') +
' ' +
loanOriginator.name
}
});
dettachCodeDialogRef.afterClosed().subscribe((response: any) => {
if (response.confirm) {
this.loansService.dettachLoanOriginator(this.loanId, String(loanOriginator.id)).subscribe((response) => {
this.reload();
});
}
});
}
/**
* Refetches data fot the component
*/
private reload() {
const url: string = this.router.url;
this.router
.navigateByUrl(`/clients/${this.clientId}/loans-accounts`, { skipLocationChange: true })
.then(() => this.router.navigate([url]));
}
}

View File

@ -658,6 +658,16 @@ export class LoansService {
return this.http.post('/loans?command=calculateLoanSchedule', payload);
}
attachLoanOriginator(loanId: string, originatorId: string): Observable<any> {
const emptyBody = {};
return this.http.post(`/loans/${loanId}/originators/${originatorId}`, emptyBody);
}
dettachLoanOriginator(loanId: string, originatorId: string): Observable<any> {
const emptyBody = {};
return this.http.delete(`/loans/${loanId}/originators/${originatorId}`, emptyBody);
}
/**
* @param loansAccount Loan account data used for the request
* @param loansAccountTemplate Loan account template for getting product default values

View File

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Currency } from 'app/shared/models/general.model';
import { CodeValue, Currency } from 'app/shared/models/general.model';
export interface DelinquencyRange {
id: number;
@ -178,6 +178,6 @@ export interface LoanOriginator {
externalId: string;
name: string;
status: string;
originatorTypeId: number;
channelTypeId: number;
originatorType: CodeValue;
channelType: CodeValue;
}

View File

@ -0,0 +1,116 @@
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="container">
<mat-card>
<form [formGroup]="loanOriginatorForm" (ngSubmit)="submit()">
<mat-card-content>
<div #createLoanOriginatorFormRef class="layout-column">
<mat-form-field>
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
<input matInput required formControlName="name" />
@if (loanOriginatorForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
@if (loanOriginatorForm.controls.name.hasError('pattern')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} <strong>{{ 'labels.inputs.cannot' | translate }}</strong>
{{ 'labels.inputs.begin with a special character or number' | translate }}
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.External Id' | translate }}</mat-label>
<input matInput required formControlName="externalId" />
@if (loanOriginatorForm.controls.externalId.hasError('required')) {
<mat-error>
{{ 'labels.inputs.External Id' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
@if (loanOriginatorForm.controls.externalId.hasError('pattern')) {
<mat-error>
{{ 'labels.inputs.External Id' | translate }} <strong>{{ 'labels.inputs.cannot' | translate }}</strong>
{{ 'labels.inputs.begin with a special character or number' | translate }}
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Status' | translate }}</mat-label>
<mat-select required formControlName="status">
@for (status of statusOptions; track status) {
<mat-option [value]="status">
{{ status }}
</mat-option>
}
</mat-select>
@if (loanOriginatorForm.controls.status.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Status' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Originator Type' | translate }}</mat-label>
<mat-select required formControlName="originatorTypeId">
@for (originatorType of originatorTypeOptions; track originatorType) {
<mat-option [value]="originatorType.id">
{{ originatorType.name }}
</mat-option>
}
</mat-select>
@if (loanOriginatorForm.controls.originatorTypeId.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Originator Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Channel Type' | translate }}</mat-label>
<mat-select required formControlName="channelTypeId">
@for (channelTypeI of channelTypeOptions; track channelTypeI) {
<mat-option [value]="channelTypeI.id">
{{ channelTypeI.name }}
</mat-option>
}
</mat-select>
@if (loanOriginatorForm.controls.channelTypeId.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Channel Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
</div>
</mat-card-content>
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
<button type="button" mat-raised-button [routerLink]="['../']">
{{ 'labels.buttons.Cancel' | translate }}
</button>
<button
mat-raised-button
color="primary"
[disabled]="!loanOriginatorForm.valid"
*mifosxHasPermission="'CREATE_LOAN_ORIGINATOR'"
>
{{ 'labels.buttons.Submit' | translate }}
</button>
</mat-card-actions>
</form>
</mat-card>
</div>

View File

@ -0,0 +1,11 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
.container {
max-width: 37rem;
}

View File

@ -0,0 +1,109 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports */
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
/** Custom Services */
import { OrganizationService } from '../../organization.service';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { CodeValue } from 'app/shared/models/general.model';
/**
* Create Loan Originator component.
*/
@Component({
selector: 'mifosx-create-loan-originator',
templateUrl: './create-loan-originator.component.html',
styleUrl: './create-loan-originator.component.scss',
imports: [
...STANDALONE_SHARED_IMPORTS
]
})
export class CreateLoanOriginatorComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private organizationService = inject(OrganizationService);
private route = inject(ActivatedRoute);
private router = inject(Router);
/** Loan Originator form. */
loanOriginatorForm: UntypedFormGroup;
/** Form data. */
loanOriginatorsTemplateData: any;
statusOptions: string[] = [];
originatorTypeOptions: CodeValue[] = [];
channelTypeOptions: CodeValue[] = [];
/* Reference of Loan Originator form */
@ViewChild('createLoanOriginatorFormRef') createLoanOriginatorFormRef: ElementRef<any>;
/* Template for popover on Loan Originator form */
@ViewChild('templateCreateLoanOriginatorForm') templateCreateLoanOriginatorForm: TemplateRef<any>;
constructor() {
this.route.data.subscribe((data: { loanOriginatorsTemplateData: any }) => {
this.loanOriginatorsTemplateData = data.loanOriginatorsTemplateData;
this.statusOptions = data.loanOriginatorsTemplateData.statusOptions;
this.originatorTypeOptions = data.loanOriginatorsTemplateData.originatorTypeOptions;
this.channelTypeOptions = data.loanOriginatorsTemplateData.channelTypeOptions;
});
}
/**
* Creates the Loan Originator form.
*/
ngOnInit() {
this.createLoanOriginatorForm();
}
/**
* Creates the Loan Originator form.
*/
createLoanOriginatorForm() {
this.loanOriginatorForm = this.formBuilder.group({
externalId: [
this.loanOriginatorsTemplateData.externalId,
Validators.required
],
name: [
'',
[
Validators.required,
Validators.pattern('(^[A-z]).*')
]
],
status: [
'',
Validators.required
],
originatorTypeId: [
'',
Validators.required
],
channelTypeId: [
'',
Validators.required
]
});
}
/**
* Submits the Loan Originator form and creates Loan Originator,
* if successful redirects to Loan Originators.
*/
submit() {
const loanOriginatorFormData = this.loanOriginatorForm.value;
const data = {
...loanOriginatorFormData
};
this.organizationService.createLoanOriginator(data).subscribe((response: any) => {
this.router.navigate(['../'], { relativeTo: this.route });
});
}
}

View File

@ -0,0 +1,116 @@
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="container">
<mat-card>
<form [formGroup]="loanOriginatorForm" (ngSubmit)="submit()">
<mat-card-content>
<div #editEmployeeFormRef class="layout-column">
<mat-form-field>
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
<input matInput required formControlName="name" />
@if (loanOriginatorForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
@if (loanOriginatorForm.controls.name.hasError('pattern')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} <strong>{{ 'labels.inputs.cannot' | translate }}</strong>
{{ 'labels.inputs.begin with a special character or number' | translate }}
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.External Id' | translate }}</mat-label>
<input matInput formControlName="externalId" readonly />
@if (loanOriginatorForm.controls.externalId.hasError('required')) {
<mat-error>
{{ 'labels.inputs.External Id' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
@if (loanOriginatorForm.controls.externalId.hasError('pattern')) {
<mat-error>
{{ 'labels.inputs.External Id' | translate }} <strong>{{ 'labels.inputs.cannot' | translate }}</strong>
{{ 'labels.inputs.begin with a special character or number' | translate }}
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Status' | translate }}</mat-label>
<mat-select required formControlName="status">
@for (status of statusOptions; track status) {
<mat-option [value]="status">
{{ status }}
</mat-option>
}
</mat-select>
@if (loanOriginatorForm.controls.status.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Status' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Originator Type' | translate }}</mat-label>
<mat-select required formControlName="originatorTypeId">
@for (originatorType of originatorTypeOptions; track originatorType) {
<mat-option [value]="originatorType.id">
{{ originatorType.name }}
</mat-option>
}
</mat-select>
@if (loanOriginatorForm.controls.originatorTypeId.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Originator Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Channel Type' | translate }}</mat-label>
<mat-select required formControlName="channelTypeId">
@for (channelTypeI of channelTypeOptions; track channelTypeI) {
<mat-option [value]="channelTypeI.id">
{{ channelTypeI.name }}
</mat-option>
}
</mat-select>
@if (loanOriginatorForm.controls.channelTypeId.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Channel Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
</div>
</mat-card-content>
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
<button type="button" mat-raised-button [routerLink]="['../']">
{{ 'labels.buttons.Cancel' | translate }}
</button>
<button
mat-raised-button
color="primary"
[disabled]="!loanOriginatorForm.valid"
*mifosxHasPermission="'UPDATE_LOAN_ORIGINATOR'"
>
{{ 'labels.buttons.Submit' | translate }}
</button>
</mat-card-actions>
</form>
</mat-card>
</div>

View File

@ -0,0 +1,11 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
.container {
max-width: 37rem;
}

View File

@ -0,0 +1,115 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports */
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
/** Custom Services */
import { OrganizationService } from '../../organization.service';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { CodeValue } from 'app/shared/models/general.model';
import { LoanOriginator } from 'app/loans/models/loan-account.model';
/**
* Create Loan Originator component.
*/
@Component({
selector: 'mifosx-edit-loan-originator',
templateUrl: './edit-loan-originator.component.html',
styleUrl: './edit-loan-originator.component.scss',
imports: [
...STANDALONE_SHARED_IMPORTS
]
})
export class EditLoanOriginatorComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private organizationService = inject(OrganizationService);
private route = inject(ActivatedRoute);
private router = inject(Router);
/** Loan Originator form. */
loanOriginatorForm: UntypedFormGroup;
/** Form data. */
loanOriginatorsData: LoanOriginator;
loanOriginatorsTemplateData: any;
statusOptions: string[] = [];
originatorTypeOptions: CodeValue[] = [];
channelTypeOptions: CodeValue[] = [];
/* Reference of Loan Originator form */
@ViewChild('editLoanOriginatorFormRef') editLoanOriginatorFormRef: ElementRef<any>;
/* Template for popover on Loan Originator form */
@ViewChild('templateCreateLoanOriginatorForm') templateCreateLoanOriginatorForm: TemplateRef<any>;
constructor() {
this.route.data.subscribe((data: { loanOriginatorData: LoanOriginator; loanOriginatorsTemplateData: any }) => {
this.loanOriginatorsData = data.loanOriginatorData;
this.loanOriginatorsTemplateData = data.loanOriginatorsTemplateData;
this.statusOptions = data.loanOriginatorsTemplateData.statusOptions;
this.originatorTypeOptions = data.loanOriginatorsTemplateData.originatorTypeOptions;
this.channelTypeOptions = data.loanOriginatorsTemplateData.channelTypeOptions;
});
}
/**
* Creates the Loan Originator form.
*/
ngOnInit() {
this.createLoanOriginatorForm();
}
/**
* Creates the Loan Originator form.
*/
createLoanOriginatorForm() {
this.loanOriginatorForm = this.formBuilder.group({
externalId: [
{
value: this.loanOriginatorsTemplateData.externalId,
disabled: true
}
],
name: [
this.loanOriginatorsData.name,
[
Validators.required,
Validators.pattern('^[A-Za-z].*')
]
],
status: [
this.loanOriginatorsData.status,
Validators.required
],
originatorTypeId: [
this.loanOriginatorsData.originatorType.id,
Validators.required
],
channelTypeId: [
this.loanOriginatorsData.channelType.id,
Validators.required
]
});
}
/**
* Submits the Loan Originator form and creates Loan Originator,
* if successful redirects to Loan Originators.
*/
submit() {
const loanOriginatorFormData = this.loanOriginatorForm.value;
delete loanOriginatorFormData.externalId;
const data = {
...loanOriginatorFormData
};
this.organizationService.updateLoanOriginator(this.loanOriginatorsData.id, data).subscribe((response: any) => {
this.router.navigate(['../..'], { relativeTo: this.route });
});
}
}

View File

@ -0,0 +1,32 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports */
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { OrganizationService } from '../organization.service';
/**
* Loan Originators data resolver.
*/
@Injectable()
export class LoanOriginatorsTemplateResolver {
private organizationService = inject(OrganizationService);
/**
* Returns the Loan Originators data.
* @returns {Observable<any>}
*/
resolve(): Observable<any> {
return this.organizationService.getLoanOriginatorsTemplate();
}
}

View File

@ -0,0 +1,99 @@
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="container m-b-20 layout-row align-end gap-20px">
<div #buttonCreateLoanOriginator>
<button mat-raised-button color="primary" [routerLink]="['create']" *mifosxHasPermission="'CREATE_LOAN_ORIGINATOR'">
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Create' | translate }} {{ 'labels.inputs.Loan Originator' | translate }}
</button>
</div>
</div>
<div class="container">
<div #filter class="layout-row gap-20px">
<mat-form-field class="flex-fill">
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
<input matInput (keyup)="applyFilter($event.target.value)" />
</mat-form-field>
</div>
<div #tableLoanOriginators class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Id' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">{{ loanOriginator.id }}</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Name' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">{{ loanOriginator.name }}</td>
</ng-container>
<ng-container matColumnDef="externalId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.External Id' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">{{ loanOriginator.externalId }}</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Status' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">
<div [className]="loanOriginator.status === 'ACTIVE' ? 'true' : 'false'">
@if (loanOriginator.status === 'ACTIVE') {
<fa-icon
icon="check-circle"
size="lg"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
@if (loanOriginator.status !== 'ACTIVE') {
<fa-icon
icon="times-circle"
size="lg"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
</div>
</td>
</ng-container>
<ng-container matColumnDef="originatorType">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Originator Type' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">{{ loanOriginator.originatorType.name }}</td>
</ng-container>
<ng-container matColumnDef="channelType">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Channel Type' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">{{ loanOriginator.channelType.name }}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let loanOriginator">
<button
type="button"
color="warn"
title="{{ 'tooltips.Delete' | translate }}"
mat-icon-button
matTooltip="{{ 'tooltips.Delete' | translate }}"
*mifosxHasPermission="'DELETE_LOAN_ORIGINATOR'"
matTooltipPosition="above"
(click)="deleteLoanOriginator(loanOriginator)"
>
<fa-icon icon="trash" size="lg"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns" [routerLink]="[row.id]" class="select-row"></tr>
</table>
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
</div>
</div>

View File

@ -0,0 +1,23 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
table {
width: 100%;
.select-row:hover {
cursor: pointer;
}
}
.true {
color: #32cd32;
}
.false {
color: #f44366;
}

View File

@ -0,0 +1,142 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports */
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, inject } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
import {
MatTableDataSource,
MatTable,
MatColumnDef,
MatHeaderCellDef,
MatHeaderCell,
MatCellDef,
MatCell,
MatHeaderRowDef,
MatHeaderRow,
MatRowDef,
MatRow
} from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Services */
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { MatTooltip } from '@angular/material/tooltip';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { LoanOriginator } from 'app/loans/models/loan-account.model';
import { OrganizationService } from '../organization.service';
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
import { TranslateService } from '@ngx-translate/core';
import { MatDialog } from '@angular/material/dialog';
import { MatIconButton } from '@angular/material/button';
/**
* Loan Originators component.
*/
@Component({
selector: 'mifosx-loan-originators',
templateUrl: './loan-originators.component.html',
styleUrl: './loan-originators.component.scss',
imports: [
...STANDALONE_SHARED_IMPORTS,
FaIconComponent,
MatTable,
MatSort,
MatColumnDef,
MatHeaderCellDef,
MatHeaderCell,
MatSortHeader,
MatCellDef,
MatCell,
MatTooltip,
MatHeaderRowDef,
MatHeaderRow,
MatRowDef,
MatRow,
MatPaginator,
MatIconButton
]
})
export class LoanOriginatorsComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private organizationService = inject(OrganizationService);
private translateService = inject(TranslateService);
private dialog = inject(MatDialog);
/** Loan Originators data. */
loanOriginatorsData: LoanOriginator[] = [];
/** Columns to be displayed in Loan Originators table. */
displayedColumns: string[] = [
'id',
'name',
'externalId',
'status',
'originatorType',
'channelType',
'actions'
];
/** Data source for Loan Originators table. */
dataSource: MatTableDataSource<any>;
/** Paginator for Loan Originators table. */
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
/** Sorter for Loan Originators table. */
@ViewChild(MatSort, { static: true }) sort: MatSort;
/* Reference of Loan Originators table */
@ViewChild('tableLoanOriginators') tableLoanOriginators: ElementRef<any>;
/* Template for popover on Loan Originators table */
@ViewChild('templateTableLoanOriginators') templateTableLoanOriginators: TemplateRef<any>;
constructor() {
this.route.data.subscribe((data: { loanOriginatorsData: LoanOriginator[] }) => {
this.loanOriginatorsData = data.loanOriginatorsData;
});
}
/**
* Filters data in Loan Originators table based on passed value.
* @param {string} filterValue Value to filter data.
*/
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
/**
* Sets the Loan Originators table.
*/
ngOnInit() {
this.setLoanOriginators();
}
/**
* Initializes the data source, paginator and sorter for Loan Originators table.
*/
setLoanOriginators() {
this.dataSource = new MatTableDataSource(this.loanOriginatorsData);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
deleteLoanOriginator(loanOriginator: LoanOriginator): void {
const deleteCodeDialogRef = this.dialog.open(DeleteDialogComponent, {
data: {
deleteContext: this.translateService.instant('labels.inputs.Loan Originator') + ' ' + loanOriginator.name
}
});
deleteCodeDialogRef.afterClosed().subscribe((response: any) => {
if (response.delete) {
this.organizationService.deleteLoanOriginator(loanOriginator.id).subscribe(() => {
this.router.navigate(['/organization/manage-loan-originators']);
});
}
});
}
}

View File

@ -0,0 +1,38 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports */
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { OrganizationService } from '../organization.service';
import { ActivatedRouteSnapshot } from '@angular/router';
/**
* Loan Originators data resolver.
*/
@Injectable()
export class LoanOriginatorsResolver {
private organizationService = inject(OrganizationService);
/**
* Returns the Loan Originators data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const originatorId = route.paramMap.get('id');
if (originatorId) {
return this.organizationService.getLoanOriginator(originatorId);
} else {
return this.organizationService.getLoanOriginators();
}
}
}

View File

@ -0,0 +1,62 @@
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="container m-b-20 layout-row align-end gap-20px">
<button mat-raised-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_LOAN_ORIGINATOR'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Edit' | translate }}
</button>
</div>
<div class="container">
<mat-card>
<mat-card-content>
<div class="layout-row-wrap">
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Name' | translate }}
</div>
<div class="flex-50">
{{ loanOriginatorData.name }}
</div>
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.External Id' | translate }}
</div>
<div class="flex-50">
{{ loanOriginatorData.externalId }}
</div>
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Status' | translate }}
</div>
<div class="flex-50">
{{ loanOriginatorData.status }}
</div>
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Originator Type' | translate }}
</div>
<div class="flex-50">
{{ loanOriginatorData.originatorType.name }}
</div>
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Channel Type' | translate }}
</div>
<div class="flex-50">
{{ loanOriginatorData.channelType.name }}
</div>
</div>
</mat-card-content>
</mat-card>
</div>

View File

@ -0,0 +1,18 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
.container {
max-width: 37rem;
.content {
div {
margin: 1rem 0;
word-wrap: break-word;
}
}
}

View File

@ -0,0 +1,43 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/** Angular Imports */
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { LoanOriginator } from 'app/loans/models/loan-account.model';
/**
* View Employee Component.
*/
@Component({
selector: 'mifosx-view-loan-originator',
templateUrl: './view-loan-originator.component.html',
styleUrl: './view-loan-originator.component.scss',
imports: [
...STANDALONE_SHARED_IMPORTS,
FaIconComponent
]
})
export class ViewLoanOriginatorComponent {
private route = inject(ActivatedRoute);
/** Employee data. */
loanOriginatorData: LoanOriginator;
/**
* Retrieves the Loan Originator data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor() {
this.route.data.subscribe((data: { loanOriginatorData: LoanOriginator }) => {
this.loanOriginatorData = data.loanOriginatorData;
});
}
}

View File

@ -111,6 +111,12 @@ import { ViewFundComponent } from './manage-funds/view-fund/view-fund.component'
import { EditFundComponent } from './manage-funds/edit-fund/edit-fund.component';
import { CreateFundComponent } from './manage-funds/create-fund/create-fund.component';
import { InvestorsComponent } from './investors/investors.component';
import { LoanOriginatorsComponent } from './loan-originators/loan-originators.component';
import { LoanOriginatorsResolver } from './loan-originators/loan-originators.resolver';
import { ViewLoanOriginatorComponent } from './loan-originators/view-loan-originator/view-loan-originator.component';
import { EditLoanOriginatorComponent } from './loan-originators/edit-loan-originator/edit-loan-originator.component';
import { CreateLoanOriginatorComponent } from './loan-originators/create-loan-originator/create-loan-originator.component';
import { LoanOriginatorsTemplateResolver } from './loan-originators/loan-originators-template.resolver';
/** Organization Routes */
const routes: Routes = [
@ -592,6 +598,50 @@ const routes: Routes = [
workingDays: WorkingDaysResolver
}
},
{
path: 'manage-loan-originators',
data: { title: 'Manage Loan Originators', breadcrumb: 'Manage Loan Originators' },
children: [
{
path: '',
component: LoanOriginatorsComponent,
resolve: {
loanOriginatorsData: LoanOriginatorsResolver
}
},
{
path: 'create',
component: CreateLoanOriginatorComponent,
data: { title: 'Create Loan Originator', breadcrumb: 'Create' },
resolve: {
loanOriginatorsTemplateData: LoanOriginatorsTemplateResolver
}
},
{
path: ':id',
data: { routeParamBreadcrumb: 'id', addBreadcrumbLink: false },
children: [
{
path: '',
component: ViewLoanOriginatorComponent,
data: { title: 'View Loan Originator', breadcrumb: 'View', routeParamBreadcrumb: false },
resolve: {
loanOriginatorData: LoanOriginatorsResolver
}
},
{
path: 'edit',
component: EditLoanOriginatorComponent,
data: { title: 'Edit Loan Originator', breadcrumb: 'Edit', routeParamBreadcrumb: false },
resolve: {
loanOriginatorData: LoanOriginatorsResolver,
loanOriginatorsTemplateData: LoanOriginatorsTemplateResolver
}
}
]
}
]
},
{
path: 'manage-funds',
data: { title: 'Manage Funds', breadcrumb: 'Manage Funds' },
@ -753,7 +803,9 @@ const routes: Routes = [
LoanProvisioningCriteriaTemplateResolver,
LoanProvisioningCriteriaAndTemplateResolver,
StandingInstructionsTemplateResolver,
AdvanceSearchTemplateResolver
AdvanceSearchTemplateResolver,
LoanOriginatorsResolver,
LoanOriginatorsTemplateResolver
]
})
export class OrganizationRoutingModule {}

View File

@ -323,6 +323,34 @@
</mat-list-item>
</div>
<div #manageLoanOriginators>
<mat-list-item *mifosxHasPermission="'READ_LOAN_ORIGINATOR'">
<div class="menu-list-item-content">
<div class="menu-left-section" [routerLink]="['manage-loan-originators']">
<mat-icon matListIcon>
<fa-icon icon="edit" size="sm"></fa-icon>
</mat-icon>
<div matLine>
{{ 'labels.heading.Manage Loan Originators' | translate }}
@if (arrowBooleans[18]) {
<p matLine [routerLink]="['manage-loan-originators']" class="menu-explanation">
{{ 'labels.text.Loan Originators are associated with loan accounts' | translate }}
</p>
}
</div>
</div>
<div class="menu-right-section">
@if (!arrowBooleans[18]) {
<fa-icon (click)="arrowBooleansToggle(18)" icon="arrow-down" size="md"></fa-icon>
}
@if (arrowBooleans[18]) {
<fa-icon (click)="arrowBooleansToggle(18)" icon="arrow-up" size="md"></fa-icon>
}
</div>
</div>
</mat-list-item>
</div>
<div #bulkloan>
<mat-list-item *mifosxHasPermission="'BULKREASSIGN_LOAN'">
<div class="menu-list-item-content">

View File

@ -67,7 +67,7 @@ export class OrganizationComponent implements AfterViewInit {
/* Template for popover on manage funds */
@ViewChild('templateManageFunds') templateManageFunds: TemplateRef<any>;
// Initialize an array of 18 boolean values, all set to false
arrowBooleans: boolean[] = new Array(18).fill(false);
arrowBooleans: boolean[] = new Array(19).fill(false);
/**
* Popover function

View File

@ -831,4 +831,46 @@ export class OrganizationService {
formData.append('dateFormat', this.settingsService.dateFormat);
return this.http.post(`${urlSuffix}/uploadtemplate`, formData, { params: httpParams });
}
/**
* @returns {Observable<any>} Loan Originators data
*/
getLoanOriginators(): Observable<any> {
return this.http.get('/loan-originators');
}
/**
* @returns {Observable<any>} Loan Originators Template data
*/
getLoanOriginatorsTemplate(): Observable<any> {
return this.http.get('/loan-originators/template');
}
/**
* @returns {Observable<any>} Loan Originator data
*/
getLoanOriginator(originatorId: string): Observable<any> {
return this.http.get(`/loan-originators/${originatorId}`);
}
/**
* @returns {Observable<any>}
*/
createLoanOriginator(payload: any): Observable<any> {
return this.http.post(`/loan-originators`, payload);
}
/**
* @returns {Observable<any>}
*/
updateLoanOriginator(originatorId: number, payload: any): Observable<any> {
return this.http.put(`/loan-originators/${originatorId}`, payload);
}
/**
* @returns {Observable<any>}
*/
deleteLoanOriginator(originatorId: number): Observable<any> {
return this.http.delete(`/loan-originators/${originatorId}`);
}
}

View File

@ -85,6 +85,7 @@ import {
faTrash,
faUndo,
faUniversity,
faUnlink,
faUserCircle,
faUser,
faUsers,
@ -271,7 +272,8 @@ export class IconsModule {
faUndo,
faReceipt,
faTableCells,
faSave
faSave,
faUnlink
);
}
}

View File

@ -1111,6 +1111,7 @@
"Manage Holidays": "Spravovat svátky",
"Manage Hooks": "Správa háčků",
"Manage Jobs": "Správa úloh",
"Manage Loan Originators": "Správa poskytovatelů úvěrů",
"Manage Offices": "Správa kanceláří",
"Manage Reports": "Správa přehledů",
"Manage Roles and Permissions": "Správa rolí a oprávnění",
@ -1976,6 +1977,7 @@
"Loan Documents": "Dokumenty o půjčce",
"Loan Id": "ID půjčky",
"Loan Officer": "Úvěrový úředník",
"Loan Originator": "Poskytovatel úvěrů",
"Loan Outstanding Amount": "Nesplacená částka úvěru",
"Loan Outstanding Percentage": "Procento nesplacené půjčky",
"Loan Parameters": "Parametry půjčky",
@ -2677,6 +2679,7 @@
"Application Menu": "Nabídka aplikací",
"Approve": "Schvalovat",
"Assign Loan Officer": "Přiřadit úvěrového úředníka",
"Attach Loan Originator": "Připojit poskytovatele půjčky",
"Assign Staff": "Přiřadit personál",
"Block Account": "Blokovat účet",
"Block Deposit": "Blokový vklad",
@ -3184,6 +3187,7 @@
"Loan Collateral Details": "Podrobnosti o zajištění úvěru",
"Loan Disbursal": "Vyplacení půjčky",
"Loan Documents": "Dokumenty o půjčce",
"Loan Originators are associated with loan accounts": "Poskytovatelé půjček jsou spojeni s účty půjček",
"Loan Products": "Úvěrové produkty",
"Loan Provisioning Criteria Organization": "Definujte kritéria pro poskytování úvěrů pro organizaci",
"Loan Tranche Details": "Podrobnosti o tranši úvěru",

View File

@ -1112,6 +1112,7 @@
"Manage Holidays": "Feiertage verwalten",
"Manage Hooks": "Hooks verwalten",
"Manage Jobs": "Jobs verwalten",
"Manage Loan Originators": "Kreditvermittler verwalten",
"Manage Offices": "Büros verwalten",
"Manage Reports": "Berichte verwalten",
"Manage Roles and Permissions": "Verwalten Sie Rollen und Berechtigungen",
@ -1977,6 +1978,7 @@
"Loan Documents": "Darlehensunterlagen",
"Loan Id": "Kredit-ID",
"Loan Officer": "Kreditsachbearbeiter",
"Loan Originator": "Kreditvermittler",
"Loan Outstanding Amount": "Ausstehender Kreditbetrag",
"Loan Outstanding Percentage": "Prozentsatz der ausstehenden Kredite",
"Loan Parameters": "Kreditparameter",
@ -2678,6 +2680,7 @@
"Application Menu": "Anwendungsmenü",
"Approve": "Genehmigen",
"Assign Loan Officer": "Weisen Sie einen Kreditsachbearbeiter zu",
"Attach Loan Originator": "Darlehensgeber hinzufügen",
"Assign Staff": "Personal zuweisen",
"Block Account": "Konto sperren",
"Block Deposit": "Blockeinzahlung",
@ -3184,6 +3187,7 @@
"Loan Collateral Details": "Details zur Kreditsicherheit",
"Loan Disbursal": "Kreditauszahlung",
"Loan Documents": "Darlehensunterlagen",
"Loan Originators are associated with loan accounts": "Kreditvermittler sind mit Kreditkonten verknüpft.",
"Loan Products": "Kreditprodukte",
"Loan Provisioning Criteria Organization": "Definieren Sie Kreditbereitstellungskriterien für die Organisation",
"Loan Tranche Details": "Details zur Darlehenstranche",

View File

@ -1125,6 +1125,7 @@
"Manage Holidays": "Manage Holidays",
"Manage Hooks": "Manage Hooks",
"Manage Jobs": "Manage Jobs",
"Manage Loan Originators": "Manage Loan Originators",
"Manage Offices": "Manage Offices",
"Manage Reports": "Manage Reports",
"Manage Roles and Permissions": "Manage Roles and Permissions",
@ -1984,6 +1985,7 @@
"Loan Documents": "Loan Documents",
"Loan Id": "Loan Id",
"Loan Officer": "Loan Officer",
"Loan Originator": "Loan Originator",
"Loan Outstanding Amount": "Loan Outstanding Amount",
"Loan Outstanding Percentage": "Loan Outstanding Percentage",
"Loan Parameters": "Loan Parameters",
@ -2686,6 +2688,7 @@
"Application Menu": "Application Menu",
"Approve": "Approve",
"Assign Loan Officer": "Assign Loan Officer",
"Attach Loan Originator": "Attach Loan Originator",
"Assign Staff": "Assign Staff",
"Block Account": "Block Account",
"Block Deposit": "Block Deposit",
@ -3279,6 +3282,7 @@
"Loan Collateral Details": "Loan Collateral Details",
"Loan Disbursal": "Loan Disbursal",
"Loan Documents": "Loan Documents",
"Loan Originators are associated with loan accounts": "Loan Originators are associated with loan accounts",
"Loan Products": "Loan Products",
"Loan Provisioning Criteria Organization": "Define Loan Provisioning Criteria for Organization",
"Loan Tranche Details": "Loan Tranche Details",

View File

@ -1112,6 +1112,7 @@
"Manage Holidays": "Administrar festivos",
"Manage Hooks": "Administrar ganchos",
"Manage Jobs": "Administrar procesos",
"Manage Loan Originators": "Administrar originadores de préstamos",
"Manage Offices": "Administrar oficinas",
"Manage Reports": "Administrar reportes",
"Manage Roles and Permissions": "Administrar roles y permisos",
@ -1977,6 +1978,7 @@
"Loan Documents": "Documentos de Crédito",
"Loan Id": "Id del Crédito",
"Loan Officer": "Oficial de Créditos",
"Loan Originator": "Originador de Créditos",
"Loan Outstanding Amount": "Monto pendiente del Crédito",
"Loan Outstanding Percentage": "Porcentaje pendiente del Crédito",
"Loan Parameters": "Parámetros del Crédito",
@ -2677,6 +2679,7 @@
"Application Menu": "Menú de aplicaciones",
"Approve": "Aprobar",
"Assign Loan Officer": "Asignar oficial de Créditos",
"Attach Loan Originator": "Adjuntar Originador de Créditos",
"Assign Staff": "Asignar Asesor",
"Block Account": "Bloquear Cuenta",
"Block Deposit": "Bloquear depósitos",
@ -3184,6 +3187,7 @@
"Loan Collateral Details": "Detalles de la garantía del Crédito",
"Loan Disbursal": "Curso del Crédito",
"Loan Documents": "Documentos de Crédito",
"Loan Originators are associated with loan accounts": "Los originadores de préstamos están asociados con cuentas de préstamos",
"Loan Products": "Productos de Crédito",
"Loan Provisioning Criteria Organization": "Definir criterios de concesión de Créditos para la organización",
"Loan Tranche Details": "Detalles de la Dispersión de Crédito",

View File

@ -1111,6 +1111,7 @@
"Manage Holidays": "Administrar festivos",
"Manage Hooks": "Administrar ganchos",
"Manage Jobs": "Administrar procesos",
"Manage Loan Originators": "Administrar originadores de préstamos",
"Manage Offices": "Administrar oficinas",
"Manage Reports": "Administrar reportes",
"Manage Roles and Permissions": "Administrar roles y permisos",
@ -1977,6 +1978,7 @@
"Loan Documents": "Documentos de Crédito",
"Loan Id": "Id del Crédito",
"Loan Officer": "Oficial de Créditos",
"Loan Originator": "Originador de Créditos",
"Loan Outstanding Amount": "Monto pendiente del Crédito",
"Loan Outstanding Percentage": "Porcentaje pendiente del Crédito",
"Loan Parameters": "Parámetros del Crédito",
@ -2680,6 +2682,7 @@
"Application Menu": "Menú de aplicaciones",
"Approve": "Aprobar",
"Assign Loan Officer": "Asignar oficial de Créditos",
"Attach Loan Originator": "Adjuntar Originador de Créditos",
"Assign Staff": "Asignar Asesor",
"Block Account": "Bloquear Cuenta",
"Block Deposit": "Bloquear depósitos",
@ -3187,6 +3190,7 @@
"Loan Collateral Details": "Detalles de la garantía del Crédito",
"Loan Disbursal": "Desembolso del Crédito",
"Loan Documents": "Documentos de Crédito",
"Loan Originators are associated with loan accounts": "Los originadores de préstamos están asociados con cuentas de préstamos",
"Loan Products": "Productos de Crédito",
"Loan Provisioning Criteria Organization": "Definir criterios de concesión de Créditos para la organización",
"Loan Tranche Details": "Detalles de la Dispersión de Crédito",

View File

@ -1112,6 +1112,7 @@
"Manage Holidays": "Gérer les jours fériés",
"Manage Hooks": "Gérer les hooks",
"Manage Jobs": "Gérer les travaux",
"Manage Loan Originators": "Gérer les courtiers en prêts",
"Manage Offices": "Gérer les bureaux",
"Manage Reports": "Gérer les rapports",
"Manage Roles and Permissions": "Gérer les rôles et les autorisations",
@ -1977,6 +1978,7 @@
"Loan Documents": "Documents de prêt",
"Loan Id": "Identifiant du prêt",
"Loan Officer": "Agent de crédit",
"Loan Originator": "Agent de prêt",
"Loan Outstanding Amount": "Encours du prêt",
"Loan Outstanding Percentage": "Pourcentage d'encours du prêt",
"Loan Parameters": "Paramètres du prêt",
@ -2676,6 +2678,7 @@
"Application Menu": "Menu des applications",
"Approve": "Approuver",
"Assign Loan Officer": "Désigner un agent de crédit",
"Attach Loan Originator": "Attacher l'initiateur de crédit",
"Assign Staff": "Affecter du personnel",
"Block Account": "Bloquer le compte",
"Block Deposit": "Dépôt en bloc",
@ -3182,6 +3185,7 @@
"Loan Collateral Details": "Détails de la garantie de prêt",
"Loan Disbursal": "Décaissement du prêt",
"Loan Documents": "Documents de prêt",
"Loan Originators are associated with loan accounts": "Les courtiers en prêts sont associés aux comptes de prêt.",
"Loan Products": "Produits de prêt",
"Loan Provisioning Criteria Organization": "Définir les critères de provisionnement des prêts pour l'organisation",
"Loan Tranche Details": "Détails de la tranche de prêt",

View File

@ -1111,6 +1111,7 @@
"Manage Holidays": "Gestisci le vacanze",
"Manage Hooks": "Gestisci gli hook",
"Manage Jobs": "Gestisci lavori",
"Manage Loan Originators": "Gestire gli originatori di prestiti",
"Manage Offices": "Gestire gli uffici",
"Manage Reports": "Gestisci rapporti",
"Manage Roles and Permissions": "Gestisci ruoli e autorizzazioni",
@ -1976,6 +1977,7 @@
"Loan Documents": "Documenti di prestito",
"Loan Id": "Identificativo prestito",
"Loan Officer": "Ufficiale di prestito",
"Loan Originator": "Originatore di prestiti",
"Loan Outstanding Amount": "Importo residuo del prestito",
"Loan Outstanding Percentage": "Percentuale del prestito in sospeso",
"Loan Parameters": "Parametri del prestito",
@ -2675,6 +2677,7 @@
"Application Menu": "Menù dell'applicazione",
"Approve": "Approvare",
"Assign Loan Officer": "Assegnare l'ufficiale di prestito",
"Attach Loan Originator": "Allega l'originatore del prestito",
"Assign Staff": "Assegnare il personale",
"Block Account": "Blocca conto",
"Block Deposit": "Deposito in blocco",
@ -3182,6 +3185,7 @@
"Loan Collateral Details": "Dettagli della garanzia del prestito",
"Loan Disbursal": "Erogazione del prestito",
"Loan Documents": "Documenti di prestito",
"Loan Originators are associated with loan accounts": "Gli originatori di prestiti sono associati ai conti di prestito",
"Loan Products": "Prodotti di prestito",
"Loan Provisioning Criteria Organization": "Definire i criteri di erogazione del prestito per l'organizzazione",
"Loan Tranche Details": "Dettagli della tranche del prestito",

View File

@ -1112,6 +1112,7 @@
"Manage Holidays": "휴일 관리",
"Manage Hooks": "후크 관리",
"Manage Jobs": "채용정보 관리",
"Manage Loan Originators": "대출 담당자 관리",
"Manage Offices": "사무실 관리",
"Manage Reports": "보고서 관리",
"Manage Roles and Permissions": "역할 및 권한 관리",
@ -1978,6 +1979,7 @@
"Loan Documents": "대출 서류",
"Loan Id": "대출 ID",
"Loan Officer": "대출 담당자",
"Loan Originator": "대출 담당자",
"Loan Outstanding Amount": "대출 미결제 금액",
"Loan Outstanding Percentage": "대출 미결제 비율",
"Loan Parameters": "대출 매개변수",
@ -2677,6 +2679,7 @@
"Application Menu": "애플리케이션 메뉴",
"Approve": "승인하다",
"Assign Loan Officer": "대출 담당자 지정",
"Attach Loan Originator": "대출 담당자 첨부",
"Assign Staff": "직원 배정",
"Block Account": "블록 계정",
"Block Deposit": "블록입금",
@ -3183,6 +3186,7 @@
"Loan Collateral Details": "대출 담보 세부정보",
"Loan Disbursal": "대출금 지급",
"Loan Documents": "대출 서류",
"Loan Originators are associated with loan accounts": "대출 담당자는 대출 계좌와 관련이 있습니다.",
"Loan Products": "대출상품",
"Loan Provisioning Criteria Organization": "조직에 대한 대출 준비 기준 정의",
"Loan Tranche Details": "대출 트랜치 세부정보",

View File

@ -1110,6 +1110,7 @@
"Manage Holidays": "Tvarkyti šventes",
"Manage Hooks": "Tvarkyti kabliukus",
"Manage Jobs": "Tvarkyti darbus",
"Manage Loan Originators": "Tvarkyti paskolų teikėjus",
"Manage Offices": "Tvarkyti biurus",
"Manage Reports": "Tvarkyti ataskaitas",
"Manage Roles and Permissions": "Tvarkykite vaidmenis ir leidimus",
@ -1975,6 +1976,7 @@
"Loan Documents": "Paskolos dokumentai",
"Loan Id": "Paskolos ID",
"Loan Officer": "Paskolos pareigūnas",
"Loan Originator": "Paskolos teikėjas",
"Loan Outstanding Amount": "Nemokėta paskolos suma",
"Loan Outstanding Percentage": "Nemokėtos paskolos procentas",
"Loan Parameters": "Paskolos parametrai",
@ -2676,6 +2678,7 @@
"Application Menu": "Programų meniu",
"Approve": "Patvirtinti",
"Assign Loan Officer": "Paskirkite paskolos pareigūną",
"Attach Loan Originator": "Pridėti paskolos teikėją",
"Assign Staff": "Paskirkite darbuotojus",
"Block Account": "Blokuoti paskyrą",
"Block Deposit": "Blokuoti indėlį",
@ -3183,6 +3186,7 @@
"Loan Collateral Details": "Paskolos užstato informacija",
"Loan Disbursal": "Paskolos išmokėjimas",
"Loan Documents": "Paskolos dokumentai",
"Loan Originators are associated with loan accounts": "Paskolų teikėjai yra susieti su paskolų sąskaitomis",
"Loan Products": "Paskolos produktai",
"Loan Provisioning Criteria Organization": "Apibrėžkite organizacijos paskolos suteikimo kriterijus",
"Loan Tranche Details": "Išsami informacija apie paskolos dalį",

View File

@ -1112,6 +1112,7 @@
"Manage Holidays": "Pārvaldīt brīvdienas",
"Manage Hooks": "Pārvaldīt āķus",
"Manage Jobs": "Pārvaldīt darbus",
"Manage Loan Originators": "Pārvaldīt aizdevumu izsniedzējus",
"Manage Offices": "Pārvaldīt birojus",
"Manage Reports": "Pārvaldīt pārskatus",
"Manage Roles and Permissions": "Pārvaldiet lomas un atļaujas",
@ -1977,6 +1978,7 @@
"Loan Documents": "Aizdevuma dokumenti",
"Loan Id": "Aizdevuma ID",
"Loan Officer": "Aizdevuma darbinieks",
"Loan Originator": "Aizdevuma izsniedzējs",
"Loan Outstanding Amount": "Aizdevuma neatmaksātā summa",
"Loan Outstanding Percentage": "Aizdevuma neatmaksātā procentuālā daļa",
"Loan Parameters": "Aizdevuma parametri",
@ -2676,6 +2678,7 @@
"Application Menu": "Lietojumprogrammu izvēlne",
"Approve": "Apstiprināt",
"Assign Loan Officer": "Norīkojiet aizdevuma speciālistu",
"Attach Loan Originator": "Pievienot aizdevuma izsniedzēju",
"Assign Staff": "Norīkojiet personālu",
"Block Account": "Bloķēt kontu",
"Block Deposit": "Bloķēt depozītu",
@ -3183,6 +3186,7 @@
"Loan Collateral Details": "Sīkāka informācija par aizdevuma nodrošinājumu",
"Loan Disbursal": "Aizdevuma izsniegšana",
"Loan Documents": "Aizdevuma dokumenti",
"Loan Originators are associated with loan accounts": "Aizdevumu izsniedzēji ir saistīti ar aizdevumu kontiem",
"Loan Products": "Aizdevuma produkti",
"Loan Provisioning Criteria Organization": "Definējiet organizācijas aizdevuma piešķiršanas kritērijus",
"Loan Tranche Details": "Sīkāka informācija par aizdevuma daļu",

View File

@ -1110,6 +1110,7 @@
"Manage Holidays": "बिदाहरू व्यवस्थापन गर्नुहोस्",
"Manage Hooks": "हुकहरू प्रबन्ध गर्नुहोस्",
"Manage Jobs": "कार्यहरू प्रबन्ध गर्नुहोस्",
"Manage Loan Originators": "ऋण सुरुवातकर्ताहरू व्यवस्थापन गर्नुहोस्",
"Manage Offices": "कार्यालयहरू प्रबन्ध गर्नुहोस्",
"Manage Reports": "रिपोर्टहरू प्रबन्ध गर्नुहोस्",
"Manage Roles and Permissions": "भूमिका र अनुमतिहरू प्रबन्ध गर्नुहोस्",
@ -1975,6 +1976,7 @@
"Loan Documents": "ऋण कागजातहरू",
"Loan Id": "ऋण आईडी",
"Loan Officer": "ऋण अधिकारी",
"Loan Originator": "ऋण प्रवर्तक",
"Loan Outstanding Amount": "ऋण बक्यौता रकम",
"Loan Outstanding Percentage": "ऋण बकाया प्रतिशत",
"Loan Parameters": "ऋण मापदण्डहरू",
@ -2674,6 +2676,7 @@
"Application Menu": "आवेदन मेनु",
"Approve": "अनुमोदन गर्नुहोस्",
"Assign Loan Officer": "ऋण अधिकारी नियुक्त गर्नुहोस्",
"Attach Loan Originator": "ऋण सुरुवातकर्ता संलग्न गर्नुहोस्",
"Assign Staff": "कर्मचारी नियुक्त गर्नुहोस्",
"Block Account": "खाता ब्लक गर्नुहोस्",
"Block Deposit": "ब्लक निक्षेप",
@ -3181,6 +3184,7 @@
"Loan Collateral Details": "ऋण संपार्श्विक विवरण",
"Loan Disbursal": "ऋण वितरण",
"Loan Documents": "ऋण कागजातहरू",
"Loan Originators are associated with loan accounts": "ऋण सुरुवातकर्ताहरू ऋण खाताहरूसँग सम्बन्धित छन्",
"Loan Products": "ऋण उत्पादनहरू",
"Loan Provisioning Criteria Organization": "संस्थाको लागि ऋण प्रावधान मापदण्ड परिभाषित गर्नुहोस्",
"Loan Tranche Details": "ऋण किस्ता विवरण",

View File

@ -1111,6 +1111,7 @@
"Manage Holidays": "Gerenciar feriados",
"Manage Hooks": "Gerenciar ganchos",
"Manage Jobs": "Gerenciar trabalhos",
"Manage Loan Originators": "Gerenciar Originadores de Empréstimos",
"Manage Offices": "Gerenciar escritórios",
"Manage Reports": "Gerenciar relatórios",
"Manage Roles and Permissions": "Gerenciar funções e permissões",
@ -1976,6 +1977,7 @@
"Loan Documents": "Documentos de empréstimo",
"Loan Id": "ID do empréstimo",
"Loan Officer": "Oficial de Empréstimo",
"Loan Originator": "Originador de empréstimo",
"Loan Outstanding Amount": "Valor pendente do empréstimo",
"Loan Outstanding Percentage": "Porcentagem pendente de empréstimo",
"Loan Parameters": "Parâmetros de empréstimo",
@ -2675,6 +2677,7 @@
"Application Menu": "Menu de aplicativos",
"Approve": "Aprovar",
"Assign Loan Officer": "Designar oficial de empréstimo",
"Attach Loan Originator": "Anexar Originador de Empréstimo",
"Assign Staff": "Atribuir equipe",
"Block Account": "Bloquear conta",
"Block Deposit": "Bloquear Depósito",
@ -3182,6 +3185,7 @@
"Loan Collateral Details": "Detalhes da garantia do empréstimo",
"Loan Disbursal": "Desembolso de empréstimo",
"Loan Documents": "Documentos de empréstimo",
"Loan Originators are associated with loan accounts": "Os originadores de empréstimos estão associados às contas de empréstimo.",
"Loan Products": "Produtos de empréstimo",
"Loan Provisioning Criteria Organization": "Definir critérios de provisionamento de empréstimos para a organização",
"Loan Tranche Details": "Detalhes da parcela do empréstimo",

View File

@ -1109,6 +1109,7 @@
"Manage Holidays": "Dhibiti Sikukuu",
"Manage Hooks": "Kusimamia Hooks",
"Manage Jobs": "Simamia Ajira",
"Manage Loan Originators": "Dhibiti Waanzilishi wa Mikopo",
"Manage Offices": "Kusimamia Ofisi",
"Manage Reports": "Dhibiti Ripoti",
"Manage Roles and Permissions": "Dhibiti Majukumu na Ruhusa",
@ -1973,6 +1974,7 @@
"Loan Documents": "Nyaraka za Mkopo",
"Loan Id": "Kitambulisho cha mkopo",
"Loan Officer": "Afisa Mikopo",
"Loan Originator": "Mwanzilishi wa Mkopo",
"Loan Outstanding Amount": "Kiasi Kilichobaki cha Mkopo",
"Loan Outstanding Percentage": "Asilimia Iliyobaki ya Mkopo",
"Loan Parameters": "Vigezo vya Mkopo",
@ -2672,6 +2674,7 @@
"Application Menu": "Menyu ya Maombi",
"Approve": "Idhinisha",
"Assign Loan Officer": "Mpe Afisa Mikopo",
"Attach Loan Originator": "Ambatisha Mwanzilishi wa Mkopo",
"Assign Staff": "Wape Wafanyakazi",
"Block Account": "Zuia Akaunti",
"Block Deposit": "Kuzuia Amana",
@ -3179,6 +3182,7 @@
"Loan Collateral Details": "Maelezo ya Dhamana ya Mkopo",
"Loan Disbursal": "Utoaji wa mkopo",
"Loan Documents": "Nyaraka za Mkopo",
"Loan Originators are associated with loan accounts": "Waanzilishi wa Mikopo wanahusishwa na akaunti za mikopo",
"Loan Products": "Bidhaa za Mkopo",
"Loan Provisioning Criteria Organization": "Bainisha Vigezo vya Utoaji wa Mkopo kwa Shirika",
"Loan Tranche Details": "Maelezo ya Mkopo",