Skip to content

Commit 8071ddd

Browse files
Merge branch 'openMF:dev' into WEB-860-Present-the-GlobalisationCode-and-translated-it-to-the-local-languages
2 parents 908d688 + 948dbee commit 8071ddd

44 files changed

Lines changed: 3756 additions & 1212 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
File renamed without changes.

package-lock.json

Lines changed: 59 additions & 596 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
"*": "prettier --check --ignore-unknown"
155155
},
156156
"overrides": {
157+
"glob": "^13.0.0",
157158
"exceljs": {
158159
"archiver": "^7.0.1",
159160
"unzipper": "^0.12.3"

src/app/clients/clients-view/clients-view.component.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,17 @@ <h3 class="flex-95">
208208
</button>
209209

210210
@if (isActive()) {
211-
<button mat-menu-item [matMenuTriggerFor]="accountApplications">
211+
<button
212+
mat-menu-item
213+
[matMenuTriggerFor]="accountApplications"
214+
*mifosxHasPermission="[
215+
'CREATE_LOAN',
216+
'CREATE_SAVINGSACCOUNT',
217+
'CREATE_SHAREACCOUNT',
218+
'CREATE_RECURRINGDEPOSITACCOUNT',
219+
'CREATE_FIXEDDEPOSITACCOUNT'
220+
]"
221+
>
212222
<mat-icon matListIcon>
213223
<fa-icon icon="money-bill-alt" size="sm"></fa-icon>
214224
</mat-icon>

src/app/core/shell/breadcrumb/breadcrumb.component.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,23 @@ export class BreadcrumbComponent implements AfterViewInit, OnDestroy {
199199
} else {
200200
url = currentUrl;
201201
}
202+
203+
// For module root breadcrumbs (e.g. "Loans", "Savings") whose URL has no entity child,
204+
// extract the correct URL from the full router URL to build a navigable link.
205+
if (url && typeof url === 'string') {
206+
const accountPathMatch = url
207+
.replace(/\/+/g, '/')
208+
.match(/\/(loans-accounts|savings-accounts|shares-accounts)\/$/);
209+
if (accountPathMatch) {
210+
const fullUrl = this.router.url.replace(/\/+/g, '/');
211+
const entityUrlMatch = fullUrl.match(new RegExp(`(.*/${accountPathMatch[1]}/\\d+)`));
212+
if (entityUrlMatch) {
213+
url = entityUrlMatch[1];
214+
} else {
215+
url = false;
216+
}
217+
}
218+
}
202219
}
203220
if (url !== undefined) {
204221
if (url.length > 8 && url.search(`/clients/`) > 0) {

src/app/loans/common-resolvers/loan-action-button.resolver.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import { Injectable, inject } from '@angular/core';
1111
import { ActivatedRouteSnapshot } from '@angular/router';
1212

1313
/** rxjs Imports */
14-
import { Observable } from 'rxjs';
14+
import { Observable, of } from 'rxjs';
15+
import { catchError } from 'rxjs/operators';
1516

1617
/** Custom Services */
1718
import { LoansService } from '../loans.service';
@@ -65,7 +66,7 @@ export class LoanActionButtonResolver {
6566
} else if (loanActionButton === 'Recovery Payment') {
6667
return this.loansService.getLoanActionTemplate(loanId, 'recoverypayment');
6768
} else if (loanActionButton === 'View Guarantors') {
68-
return this.loansService.getLoanAccountResource(loanId, 'guarantors');
69+
return this.loansService.getGuarantors(loanId).pipe(catchError(() => of([])));
6970
} else if (loanActionButton === 'Create Guarantor') {
7071
return this.loansService.getGuarantorTemplate(loanId);
7172
} else if (loanActionButton === 'Disburse') {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!--
2+
Copyright since 2025 Mifos Initiative
3+
4+
This Source Code Form is subject to the terms of the Mozilla Public
5+
License, v. 2.0. If a copy of the MPL was not distributed with this
6+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
-->
8+
9+
<h1 mat-dialog-title>{{ 'labels.heading.Edit Guarantor' | translate }}</h1>
10+
11+
<div mat-dialog-content>
12+
<form [formGroup]="editGuarantorForm" class="layout-column">
13+
<mat-form-field>
14+
<mat-label>{{ 'labels.inputs.First Name' | translate }}</mat-label>
15+
<input matInput formControlName="firstname" />
16+
</mat-form-field>
17+
<mat-form-field>
18+
<mat-label>{{ 'labels.inputs.Last Name' | translate }}</mat-label>
19+
<input matInput formControlName="lastname" />
20+
</mat-form-field>
21+
<mat-form-field>
22+
<mat-label>{{ 'labels.inputs.Relationship' | translate }}</mat-label>
23+
<mat-select formControlName="clientRelationshipTypeId">
24+
@for (relationType of relationTypes; track relationType) {
25+
<mat-option [value]="relationType.id">
26+
{{ relationType.name }}
27+
</mat-option>
28+
}
29+
</mat-select>
30+
</mat-form-field>
31+
<mat-form-field>
32+
<mat-label>{{ 'labels.inputs.Address Line' | translate }} 1</mat-label>
33+
<input matInput formControlName="addressLine1" />
34+
</mat-form-field>
35+
<mat-form-field>
36+
<mat-label>{{ 'labels.inputs.Address Line' | translate }} 2</mat-label>
37+
<input matInput formControlName="addressLine2" />
38+
</mat-form-field>
39+
<mat-form-field>
40+
<mat-label>{{ 'labels.inputs.City' | translate }}</mat-label>
41+
<input matInput formControlName="city" />
42+
</mat-form-field>
43+
<mat-form-field>
44+
<mat-label>{{ 'labels.inputs.Zip' | translate }}</mat-label>
45+
<input matInput formControlName="zip" />
46+
</mat-form-field>
47+
<mat-form-field>
48+
<mat-label>{{ 'labels.inputs.Mobile' | translate }}</mat-label>
49+
<input type="tel" matInput formControlName="mobileNumber" />
50+
</mat-form-field>
51+
<mat-form-field>
52+
<mat-label>{{ 'labels.inputs.Residence Phone' | translate }} #</mat-label>
53+
<input type="tel" matInput formControlName="housePhoneNumber" />
54+
</mat-form-field>
55+
</form>
56+
</div>
57+
58+
<mat-dialog-actions class="layout-row layout-xs-column layout-align-center gap-2percent">
59+
<button mat-raised-button mat-dialog-close>{{ 'labels.buttons.Cancel' | translate }}</button>
60+
<button mat-raised-button color="primary" (click)="submit()">{{ 'labels.buttons.Submit' | translate }}</button>
61+
</mat-dialog-actions>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Copyright since 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Copyright since 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
8+
9+
import { Component, OnInit, inject } from '@angular/core';
10+
import {
11+
MatDialogRef,
12+
MAT_DIALOG_DATA,
13+
MatDialogTitle,
14+
MatDialogContent,
15+
MatDialogActions,
16+
MatDialogClose
17+
} from '@angular/material/dialog';
18+
import { UntypedFormGroup, UntypedFormBuilder, ReactiveFormsModule } from '@angular/forms';
19+
import { CdkScrollable } from '@angular/cdk/scrolling';
20+
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
21+
22+
@Component({
23+
selector: 'mifosx-edit-guarantor-dialog',
24+
templateUrl: './edit-guarantor-dialog.component.html',
25+
styleUrls: ['./edit-guarantor-dialog.component.scss'],
26+
imports: [
27+
...STANDALONE_SHARED_IMPORTS,
28+
MatDialogTitle,
29+
CdkScrollable,
30+
MatDialogContent,
31+
MatDialogActions,
32+
MatDialogClose,
33+
ReactiveFormsModule
34+
]
35+
})
36+
export class EditGuarantorDialogComponent implements OnInit {
37+
dialogRef = inject<MatDialogRef<EditGuarantorDialogComponent>>(MatDialogRef);
38+
data = inject(MAT_DIALOG_DATA);
39+
private formBuilder = inject(UntypedFormBuilder);
40+
41+
editGuarantorForm: UntypedFormGroup;
42+
relationTypes: any[] = [];
43+
44+
ngOnInit() {
45+
this.relationTypes = this.data.relationTypes || [];
46+
const guarantor = this.data.guarantorData;
47+
this.editGuarantorForm = this.formBuilder.group({
48+
firstname: [guarantor.firstname || ''],
49+
lastname: [guarantor.lastname || ''],
50+
clientRelationshipTypeId: [guarantor.clientRelationshipType?.id || ''],
51+
addressLine1: [guarantor.addressLine1 || ''],
52+
addressLine2: [guarantor.addressLine2 || ''],
53+
city: [guarantor.city || ''],
54+
zip: [guarantor.zip || ''],
55+
mobileNumber: [guarantor.mobileNumber || ''],
56+
housePhoneNumber: [guarantor.housePhoneNumber || '']
57+
});
58+
}
59+
60+
submit() {
61+
this.dialogRef.close(this.editGuarantorForm.value);
62+
}
63+
}

src/app/loans/custom-dialog/loans-account-view-guarantor-details-dialog/loans-account-view-guarantor-details-dialog.component.html

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,30 @@
99
<h1 mat-dialog-title>{{ 'labels.heading.Guarantor Detail' | translate }}</h1>
1010

1111
<div mat-dialog-content class="layout-column">
12-
<div class="layout-row-wrap responsive-column">
12+
<div class="layout-column">
1313
<div class="flex-fill">
14-
<span class="flex-50">{{ 'labels.inputs.First Name' | translate }}:</span>
15-
<span class="flex-50">{{ data.guarantorData.firstname }}</span>
14+
<span class="flex-40">{{ 'labels.inputs.First Name' | translate }}:</span>
15+
<span class="flex-60">{{ data.guarantorData.firstname }}</span>
1616
</div>
1717

1818
<div class="flex-fill">
19-
<span class="flex-50">{{ 'labels.inputs.Last Name' | translate }}:</span>
20-
<span class="flex-50">{{ data.guarantorData.lastname }}</span>
19+
<span class="flex-40">{{ 'labels.inputs.Last Name' | translate }}:</span>
20+
<span class="flex-60">{{ data.guarantorData.lastname }}</span>
2121
</div>
2222

2323
<div class="flex-fill">
24-
<span class="flex-50">{{ 'labels.inputs.Relationship' | translate }}:</span>
25-
<span class="flex-50">{{ data.guarantorData.clientRelationshipType.name }}</span>
24+
<span class="flex-40">{{ 'labels.inputs.Relationship' | translate }}:</span>
25+
<span class="flex-60">{{ data.guarantorData.clientRelationshipType?.name }}</span>
2626
</div>
2727

2828
<div class="flex-fill">
29-
<span class="flex-50">{{ 'labels.inputs.Guarantor Type' | translate }}:</span>
30-
<span class="flex-50">{{ data.guarantorData.guarantorType.value }}</span>
29+
<span class="flex-40">{{ 'labels.inputs.Guarantor Type' | translate }}:</span>
30+
<span class="flex-60">{{ data.guarantorData.guarantorType?.value }}</span>
3131
</div>
3232

3333
<div class="flex-fill">
34-
<span class="flex-50">{{ 'labels.inputs.Status' | translate }}:</span>
35-
<span class="flex-50">
34+
<span class="flex-40">{{ 'labels.inputs.Status' | translate }}:</span>
35+
<span class="flex-60">
3636
@if (data.guarantorData.status) {
3737
<span>
3838
{{ 'labels.inputs.Active' | translate }}
@@ -47,11 +47,11 @@ <h1 mat-dialog-title>{{ 'labels.heading.Guarantor Detail' | translate }}</h1>
4747
</div>
4848
@if (data.loanData?.delinquent?.availableDisbursementAmountWithOverApplied !== undefined) {
4949
<div class="flex-fill">
50-
<span class="flex-50"
50+
<span class="flex-40"
5151
>{{ 'labels.inputs.Available Disbursement Amount (with Over Applied)' | translate }}:</span
5252
>
53-
<span class="flex-50">{{
54-
data.loanData.delinquent.availableDisbursementAmountWithOverApplied | formatNumber
53+
<span class="flex-60">{{
54+
data.loanData?.delinquent?.availableDisbursementAmountWithOverApplied | formatNumber
5555
}}</span>
5656
</div>
5757
}

0 commit comments

Comments
 (0)