Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** Angular Imports */
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { I18nService } from './core/i18n/i18n.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
HttpBackend,
Expand Down Expand Up @@ -130,7 +131,9 @@ export function HttpLoaderFactory(http: HttpClient) {
provide: HTTP_INTERCEPTORS,
useClass: !environment.OIDC.oidcServerEnabled ? TokenInterceptor : ZitadelTokenInterceptor,
multi: true
}
},
I18nService

]
})
export class AppModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -177,37 +177,42 @@ export class CreateGlimAccountComponent {
};
}

setData(client: any, totalLoan: number): any {
setData(applicationId: number, client: any, totalLoan: number, isFirst: boolean, isLast: boolean): any {
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
// const monthDayFormat = 'dd MMMM';
const data = {
const data: any = {
...this.loansAccount,
charges: this.loansAccount.charges.map((charge: any) => ({
chargeId: charge.id,
amount: charge.amount
amount: charge.amount,
currency: charge.currency
})),
clientId: client.id,
totalLoan: totalLoan,
loanType: 'glim',
applicationId: applicationId,
amortizationType: 1,
isParentAccount: true,
principal: client.principal,
syncDisbursementWithMeeting: false,
expectedDisbursementDate: this.dateUtils.formatDate(this.loansAccount.expectedDisbursementDate, dateFormat),
submittedOnDate: this.dateUtils.formatDate(this.loansAccount.submittedOnDate, dateFormat),
dateFormat,
// monthDayFormat,
locale
dateFormat: dateFormat,
locale: locale,
groupId: this.loansAccountTemplate.group.id
};
data.groupId = this.loansAccountTemplate.group.id;

if (isFirst) {
data.isParentAccount = true;
}
if (isLast) {
data.lastApplication = true;
}
delete data.principalAmount;
// TODO: 2025-03-17: Apparently (?!) unsupported for GLIM
delete data.allowPartialPeriodInterestCalculation;
delete data.multiDisburseLoan;
delete data.isFloatingInterestRate;

delete data.moratoriumPrincipal;
delete data.moratoriumInterest;
return JSON.stringify(data);
}

Expand All @@ -216,12 +221,17 @@ export class CreateGlimAccountComponent {
const requestData = [];
const memberSelected = this.selectedMembers?.selectedMembers ?? [];
const totalLoan = this.totalLoanAmount();
const applicationId = Math.floor(1000000000 + Math.random() * 9000000000);

for (let index = 0; index < memberSelected.length; index++) {
const isFirst = index === 0;
const isLast = index === memberSelected.length - 1;
requestData.push({
requestId: index.toString(),
reference: index === 0 ? null : (index - 1).toString(),
method: 'POST',
relativeUrl: 'loans',
body: this.setData(memberSelected[index], totalLoan)
body: this.setData(applicationId, memberSelected[index], totalLoan, isFirst, isLast)
});
}
return requestData;
Expand All @@ -236,57 +246,10 @@ export class CreateGlimAccountComponent {
return total;
}

/**
* Creates a new GLIM account.
*/
submit() {
this.selectedMembers = this.loansActiveClientMembers?.selectedClientMembers;
const memberSelected = this.loansActiveClientMembers?.selectedClientMembers?.selectedMembers ?? [];
if (!memberSelected.length) return;
const gsimMemberIds = new Set(this.dataSource.map((m: any) => Number(m.id)));
for (const member of memberSelected) {
const memberId = Number(member.id);
// Validate savings account ownership
const ownerId = Number(member.linkAccountOwnerId);
if (member.linkAccountId && member.linkAccountOwnerId && ownerId !== memberId) {
this.i18nService.translate('errors.linkedSavingsAccountOwnership').subscribe((msg: string) => {
this.notify({ defaultUserMessage: msg, errors: [] }, { memberId });
});
return;
}
// Validate GSIM membership
if (!gsimMemberIds.has(memberId)) {
this.i18nService.translate('errors.clientNotInGSIM', { id: memberId }).subscribe((msg: string) => {
this.notify({ defaultUserMessage: msg, errors: [] }, { memberId });
});
return;
}
}

// Use date format from settingsService for interestChargedFromDate
const data = this.buildRequestData();
this.loansService.createGlimAccount(data).subscribe((response: any) => {
const body = JSON.parse(response[0].body);
if (body.glimId) {
this.router.navigate(
[
'../',
body.glimId
],
{ relativeTo: this.route }
);
} else {
this.notify(body, { batchSize: data.length });
}
});
}

notify(body: any, context?: { [k: string]: unknown }) {
const parts: string[] = [String(body?.defaultUserMessage ?? '')];
if (Array.isArray(body?.errors)) {
for (const e of body.errors) parts.push(String(e?.developerMessage ?? ''));
}
if (context) parts.push(`Context: ${JSON.stringify(context)}`);
console.error(parts.join(' ').trim());
notify(body: any, data: any) {
let message = body.defaultUserMessage + ' ';
body.errors?.forEach((error: any) => (message += error.developerMessage + ' '));
message += 'Data: ' + JSON.stringify(data);
console.error(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
{{ charge.name }}<span *ngIf="charge.currency">, {{ charge.currency.displaySymbol }}</span>
</td>
</ng-container>

Expand All @@ -39,7 +39,13 @@
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount }}
<button mat-icon-button color="primary" (click)="editChargeAmount(charge)">
<button
mat-icon-button
color="primary"
(click)="editChargeAmount(charge)"
type="button"
aria-label="Edit charge amount"
>
<fa-icon icon="pen"></fa-icon>
</button>
</td>
Expand Down Expand Up @@ -84,6 +90,8 @@
charge.chargeTimeType.value === 'Specified due date'
"
(click)="editChargeDate(charge)"
type="button"
aria-label="Edit charge date"
>
<fa-icon icon="pen"></fa-icon>
</button>
Expand All @@ -93,7 +101,7 @@
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let charge">
<button mat-icon-button color="warn" (click)="deleteCharge(charge)">
<button mat-icon-button color="warn" (click)="deleteCharge(charge)" type="button" aria-label="Delete charge">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
Expand All @@ -110,7 +118,9 @@ <h4 class="mat-h4 flex-98">{{ 'labels.heading.Overdue Charges' | translate }}</h
<table mat-table class="mat-elevation-z1" [dataSource]="overDueChargesDataSource">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th>
<td mat-cell *matCellDef="let charge">{{ charge.name }},{{ charge.currency.displaySymbol }}</td>
<td mat-cell *matCellDef="let charge">
{{ charge.name }}<span *ngIf="charge.currency">, {{ charge.currency.displaySymbol }}</span>
</td>
</ng-container>

<ng-container matColumnDef="type">
Expand All @@ -120,7 +130,18 @@ <h4 class="mat-h4 flex-98">{{ 'labels.heading.Overdue Charges' | translate }}</h

<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let charge">{{ charge.amount | formatNumber }}</td>
<td mat-cell *matCellDef="let charge">
{{ charge.amount | formatNumber }}
<button
mat-icon-button
color="primary"
(click)="editOverdueChargeAmount(charge)"
type="button"
aria-label="Edit overdue charge amount"
>
<fa-icon icon="pen"></fa-icon>
</button>
</td>
</ng-container>

<ng-container matColumnDef="collectedon">
Expand All @@ -134,15 +155,15 @@ <h4 class="mat-h4 flex-98">{{ 'labels.heading.Overdue Charges' | translate }}</h
</div>

<div class="layout-row responsive-column align-center gap-2px margin-t">
<button mat-raised-button matStepperPrevious>
<button mat-raised-button matStepperPrevious type="button">
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}
</button>
<button mat-raised-button matStepperNext>
<button mat-raised-button matStepperNext type="button">
{{ 'labels.buttons.Next' | translate }}
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
<button mat-raised-button *ngIf="loanId" [routerLink]="['../', 'general']">
<button mat-raised-button *ngIf="loanId" [routerLink]="['../', 'general']" type="button">
{{ 'labels.buttons.Cancel' | translate }}
</button>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,33 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
});
}

editOverdueChargeAmount(charge: { amount: number; [key: string]: any }) {
const formfields: FormfieldBase[] = [
new InputBase({
controlName: 'amount',
label: 'Amount',
value: charge.amount,
type: 'number',
required: false
})

];
const data = {
title: 'Edit Overdue Charge Amount',
layout: { addButtonText: 'Confirm' },
formfields: formfields
};
const editNoteDialogRef = this.dialog.open(FormDialogComponent, { data });
editNoteDialogRef.afterClosed().subscribe((response?: { data?: { value: { amount: number } } }) => {
if (response?.data) {
const newCharge = { ...charge, amount: response.data.value.amount };
this.overDueChargesDataSource.splice(this.overDueChargesDataSource.indexOf(charge), 1, newCharge);
this.overDueChargesDataSource = this.overDueChargesDataSource.concat([]);
this.pristine = false;
}
});
}

get isValid() {
return true;
// !this.activeClientMembers ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,14 @@ <h3 class="mat-h3 flex-fill">{{ 'labels.heading.Charges' | translate }}</h3>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
{{ charge.name }}<span *ngIf="charge.currency">, {{ charge.currency.displaySymbol }}</span>
</td>
</ng-container>

<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
{{ charge.chargeCalculationType?.value || '' }}
</td>
</ng-container>

Expand All @@ -283,28 +283,30 @@ <h3 class="mat-h3 flex-fill">{{ 'labels.heading.Charges' | translate }}</h3>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
{{ charge.chargeTimeType?.value || '' }}
</td>
</ng-container>

<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Date' | translate }}</th>
<td mat-cell *matCellDef="let charge">
<span
*ngIf="charge.chargeTimeType.value === 'Specified due date' || charge.chargeTimeType.value === 'Weekly Fee'"
*ngIf="
charge.chargeTimeType?.value === 'Specified due date' || charge.chargeTimeType?.value === 'Weekly Fee'
"
>
{{ (charge.dueDate | dateFormat) || 'Unassigned' }}
</span>
<span *ngIf="charge.chargeTimeType.value === 'Monthly Fee' || charge.chargeTimeType.value === 'Annual Fee'">
<span *ngIf="charge.chargeTimeType?.value === 'Monthly Fee' || charge.chargeTimeType?.value === 'Annual Fee'">
{{ (charge.feeOnMonthDay | dateFormat) || 'Unassigned' }}
</span>
<span
*ngIf="
!(
charge.chargeTimeType.value === 'Monthly Fee' ||
charge.chargeTimeType.value === 'Annual Fee' ||
charge.chargeTimeType.value === 'Specified due date' ||
charge.chargeTimeType.value === 'Weekly Fee'
charge.chargeTimeType?.value === 'Monthly Fee' ||
charge.chargeTimeType?.value === 'Annual Fee' ||
charge.chargeTimeType?.value === 'Specified due date' ||
charge.chargeTimeType?.value === 'Weekly Fee'
)
"
>
Expand All @@ -329,7 +331,9 @@ <h3 class="mat-h3 flex-98">{{ 'labels.heading.Overdue Charges' | translate }}</h
<table mat-table class="mat-elevation-z1" [dataSource]="loansAccountProductTemplate.overdueCharges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th>
<td mat-cell *matCellDef="let charge">{{ charge.name }},{{ charge.currency.displaySymbol }}</td>
<td mat-cell *matCellDef="let charge">
{{ charge.name }}<span *ngIf="charge.currency">,{{ charge.currency.displaySymbol }}</span>
</td>
</ng-container>

<ng-container matColumnDef="type">
Expand Down
Loading