Documents and Notes for Clients, Loans and Clients (#1632)

Co-authored-by: Jose Alberto Hernandez <alberto@MacBook-Pro.local>
This commit is contained in:
José Alberto Hernández
2023-01-05 03:19:41 -06:00
committed by GitHub
co-authored by Jose Alberto Hernandez
parent 28d5d7595f
commit cafe8fa73d
57 changed files with 1119 additions and 468 deletions
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { SavingDocumentsResolver } from './saving-documents.resolver';
describe('SavingDocumentsResolver', () => {
let resolver: SavingDocumentsResolver;
beforeEach(() => {
TestBed.configureTestingModule({});
resolver = TestBed.inject(SavingDocumentsResolver);
});
it('should be created', () => {
expect(resolver).toBeTruthy();
});
});
@@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';
import {
Resolve,
ActivatedRouteSnapshot
} from '@angular/router';
import { Observable } from 'rxjs';
import { SavingsService } from '../savings.service';
@Injectable({
providedIn: 'root'
})
export class SavingDocumentsResolver implements Resolve<boolean> {
/**
* @param {SavingsService} savingsService Savings service.
*/
constructor(private savingsService: SavingsService) { }
/**
* Returns the Savings data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const savingAccountId = route.parent.paramMap.get('savingAccountId');
return this.savingsService.getSavingsDocuments(savingAccountId);
}
}
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { SavingNotesResolver } from './saving-notes.resolver';
describe('SavingNotesResolver', () => {
let resolver: SavingNotesResolver;
beforeEach(() => {
TestBed.configureTestingModule({});
resolver = TestBed.inject(SavingNotesResolver);
});
it('should be created', () => {
expect(resolver).toBeTruthy();
});
});
@@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';
import {
Resolve,
ActivatedRouteSnapshot
} from '@angular/router';
import { Observable } from 'rxjs';
import { SavingsService } from '../savings.service';
@Injectable({
providedIn: 'root'
})
export class SavingNotesResolver implements Resolve<boolean> {
/**
* @param {SavingsService} savingsService Savings service.
*/
constructor(private savingsService: SavingsService) { }
/**
* Returns the Savings data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const savingAccountId = route.parent.paramMap.get('savingAccountId');
return this.savingsService.getSavingsNotes(savingAccountId);
}
}
@@ -135,7 +135,7 @@ export class ChargesTabComponent implements OnInit {
dateFormat,
locale
};
this.savingsService.executeSavingsAccountChargesCommand(this.savingsAccountData.id, 'paycharge', dataObject, chargeId)
this.savingsService.executeSavingsAccountChargesCommand(this.savingsAccountData.id, 'pay', dataObject, chargeId)
.subscribe(() => {
this.reload();
});
@@ -0,0 +1,7 @@
<mifosx-entity-notes-tab [entityId]="entityId"
[entityNotes]="entityNotes"
[callbackAdd]="addNote"
[callbackEdit]="editNote"
[callbackDelete]="deleteNote"
>
</mifosx-entity-notes-tab>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NotesTabComponent } from './notes-tab.component';
describe('NotesTabComponent', () => {
let component: NotesTabComponent;
let fixture: ComponentFixture<NotesTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ NotesTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(NotesTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,55 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AuthenticationService } from 'app/core/authentication/authentication.service';
import { SavingsService } from 'app/savings/savings.service';
@Component({
selector: 'mifosx-notes-tab',
templateUrl: './notes-tab.component.html',
styleUrls: ['./notes-tab.component.scss']
})
export class NotesTabComponent implements OnInit {
entityId: string;
username: string;
entityNotes: any;
constructor(private route: ActivatedRoute,
private savingsService: SavingsService,
private authenticationService: AuthenticationService) {
const savedCredentials = this.authenticationService.getCredentials();
this.username = savedCredentials.username;
this.entityId = this.route.parent.snapshot.params['savingAccountId'];
this.route.data.subscribe((data: { savingAccountNotes: any }) => {
this.entityNotes = data.savingAccountNotes;
});
}
ngOnInit() {
}
addNote(noteContent: any) {
this.savingsService.createSavingsNote(this.entityId, noteContent).subscribe((response: any) => {
this.entityNotes.push({
id: response.resourceId,
createdByUsername: this.username,
createdOn: new Date(),
note: noteContent
});
});
}
editNote(noteId: string, noteContent: any, index: number) {
this.savingsService.editSavingsNote(this.entityId, noteId, noteContent).subscribe(() => {
this.entityNotes[index].note = noteContent.note;
});
}
deleteNote(noteId: string, index: number) {
this.savingsService.deleteSavingsNote(this.entityId, noteId)
.subscribe(() => {
this.entityNotes.splice(index, 1);
});
}
}
@@ -34,10 +34,10 @@
{{entityType}} Name: {{savingsAccountData.clientName || savingsAccountData.groupName}}
<span class="m-l-10" *ngIf="savingsAccountData.clientAccountNo">({{savingsAccountData.clientAccountNo}})</span><br />
<span *ngIf="!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval">
Current Balances:
Current Balances :
{{savingsAccountData.currency.displaySymbol}}<span class="m-l-10">{{savingsAccountData.summary.accountBalance |
number}}</span><br />
Available Balance:
Available Balance :
{{savingsAccountData.currency.displaySymbol}}<span class="m-l-10">{{savingsAccountData.summary.availableBalance |
number}}</span>
</span>
@@ -310,6 +310,14 @@
[active]="charges.isActive">
Charges
</a>
<a mat-tab-link [routerLink]="['./documents']" routerLinkActive #savingsDocuments="routerLinkActive"
[active]="savingsDocuments.isActive">
Savings Documents
</a>
<a mat-tab-link *mifosxHasPermission="'READ_SAVINGSNOTE'" [routerLink]="['./notes']" routerLinkActive #notes="routerLinkActive"
[active]="notes.isActive">
Notes
</a>
<ng-container *mifosxHasPermission="'READ_SAVINGSACCOUNTCHARGE'">
<a mat-tab-link [routerLink]="['./standing-instructions']" routerLinkActive
#standingInstructions="routerLinkActive" [active]="standingInstructions.isActive"
@@ -0,0 +1,7 @@
<mifosx-entity-documents-tab [entityType]="entityType" [entityId]="entityId"
[entityDocuments]="entityDocuments"
[callbackUpload]="uploadDocument"
[callbackDownload]="downloadDocument"
[callbackDelete]="deleteDocument"
>
</mifosx-entity-documents-tab>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SavingsDocumentsTabComponent } from './savings-documents-tab.component';
describe('SavingsDocumentsTabComponent', () => {
let component: SavingsDocumentsTabComponent;
let fixture: ComponentFixture<SavingsDocumentsTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SavingsDocumentsTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SavingsDocumentsTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,71 @@
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute } from '@angular/router';
import { UploadDocumentDialogComponent } from 'app/clients/clients-view/custom-dialogs/upload-document-dialog/upload-document-dialog.component';
import { SavingsService } from 'app/savings/savings.service';
import { SettingsService } from 'app/settings/settings.service';
import { environment } from 'environments/environment';
@Component({
selector: 'mifosx-savings-documents-tab',
templateUrl: './savings-documents-tab.component.html',
styleUrls: ['./savings-documents-tab.component.scss']
})
export class SavingsDocumentsTabComponent implements OnInit {
/** Stores the resolved savings documents data */
entityDocuments: any;
/** Stores the saving Account Id */
entityId: string;
entityType: string = 'savings';
/**
* Retrieves the savings data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute,
private savingsService: SavingsService,
private settingsService: SettingsService,
public dialog: MatDialog) {
this.route.data.subscribe((data: { savingsDocuments: any }) => {
this.setSavingsDocumentsData(data.savingsDocuments);
});
this.entityId = this.route.parent.snapshot.params['savingAccountId'];
}
ngOnInit() {
}
setSavingsDocumentsData(data: any) {
data.forEach((ele: any) => {
ele.docUrl = this.settingsService.serverUrl + '/savings/' + ele.parentEntityId + '/documents/' + ele.id + '/attachment?tenantIdentifier=' + environment.fineractPlatformTenantId;
if (ele.fileName) {
if (ele.fileName.toLowerCase().indexOf('.jpg') !== -1 || ele.fileName.toLowerCase().indexOf('.jpeg') !== -1 || ele.fileName.toLowerCase().indexOf('.png') !== -1) {
ele.fileIsImage = true;
}
}
if (ele.type) {
if (ele.type.toLowerCase().indexOf('image') !== -1) {
ele.fileIsImage = true;
}
}
});
this.entityDocuments = data;
}
downloadDocument(parentEntityId: string, documentId: string) {
this.savingsService.downloadSavingsDocument(parentEntityId, documentId).subscribe(res => {
const url = window.URL.createObjectURL(res);
window.open(url);
});
}
uploadDocument(formData: FormData): any {
return this.savingsService.loadSavingsDocument(this.entityId, formData);
}
deleteDocument(documentId: any) {
this.savingsService.deleteSavingsDocument(this.entityId, documentId).subscribe((res: any) => {});
}
}
@@ -93,7 +93,7 @@ export class ViewChargeComponent {
dateFormat,
locale
};
this.savingsService.executeSavingsAccountChargesCommand(this.chargeData.accountId, 'paycharge', dataObject, this.chargeData.id)
this.savingsService.executeSavingsAccountChargesCommand(this.chargeData.accountId, 'pay', dataObject, this.chargeData.id)
.subscribe(() => {
this.reload();
});
+41
View File
@@ -37,6 +37,11 @@ import { GSIMAccountsResolver } from 'app/groups/common-resolvers/gsim-account-r
import { GroupAccountsResolver } from 'app/groups/common-resolvers/group-account.resolver';
import { GSIMViewResolver } from './gsim-account/gsim-account.resolver';
import { GroupViewResolver } from 'app/groups/common-resolvers/group-view.resolver';
import { SavingsDocumentsTabComponent } from './savings-account-view/savings-documents-tab/savings-documents-tab.component';
import { NotesTabComponent } from './savings-account-view/notes-tab/notes-tab.component';
import { SavingNotesResolver } from './common-resolvers/saving-notes.resolver';
import { SavingDocumentsResolver } from './common-resolvers/saving-documents.resolver';
import { DocumentsTabComponent } from 'app/clients/clients-view/documents-tab/documents-tab.component';
/** Savings Routes */
const routes: Routes = [
{
@@ -91,6 +96,22 @@ const routes: Routes = [
component: StandingInstructionsTabComponent,
data: { title: extract('Savings Account SIH'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false }
},
{
path: 'notes',
component: NotesTabComponent,
data: { title: extract('Savings Account Notes'), breadcrumb: 'Notes', routeParamBreadcrumb: false },
resolve: {
savingAccountNotes: SavingNotesResolver
}
},
{
path: 'documents',
component: DocumentsTabComponent,
data: { title: extract('Savings Account Documents'), breadcrumb: 'Documents', routeParamBreadcrumb: false },
resolve: {
savingAccountDocuments: SavingDocumentsResolver
}
},
{
path: 'datatables',
children: [
@@ -184,6 +205,26 @@ const routes: Routes = [
savingsAccountActionData: SavingsAccountActionsResolver
}
},
{
path: 'documents',
data: { title: extract('Savings Account Documents'), breadcrumb: 'Documents', routeParamBreadcrumb: false },
children: [
{
path: '',
redirectTo: '../documents', pathMatch: 'prefix'
},
]
},
{
path: 'notes',
data: { title: extract('Savings Account Notes'), breadcrumb: 'Notes', routeParamBreadcrumb: false },
children: [
{
path: '',
redirectTo: '../notes', pathMatch: 'prefix'
},
]
},
{
path: 'transfer-funds',
loadChildren: () => import('../account-transfers/account-transfers.module').then(m => m.AccountTransfersModule)
+5 -1
View File
@@ -49,6 +49,8 @@ import { GsimAccountComponent } from './gsim-account/gsim-account.component';
import { CreateGsimAccountComponent } from './gsim-account/create-gsim-account/create-gsim-account.component';
import { ManageSavingsAccountComponent } from './saving-account-actions/manage-savings-account/manage-savings-account.component';
import { ReleaseAmountDialogComponent } from './savings-account-view/custom-dialogs/release-amount-dialog/release-amount-dialog.component';
import { SavingsDocumentsTabComponent } from './savings-account-view/savings-documents-tab/savings-documents-tab.component';
import { NotesTabComponent } from './savings-account-view/notes-tab/notes-tab.component';
/**
@@ -104,7 +106,9 @@ import { ReleaseAmountDialogComponent } from './savings-account-view/custom-dial
GsimAccountComponent,
CreateGsimAccountComponent,
ManageSavingsAccountComponent,
ReleaseAmountDialogComponent
ReleaseAmountDialogComponent,
SavingsDocumentsTabComponent,
NotesTabComponent
],
providers: [ ]
})
+57
View File
@@ -286,4 +286,61 @@ export class SavingsService {
return this.http.post(`/savingsaccounts/gsim`, gsimData);
}
/**
* @param savingAccountId Savings Id
* @returns The notes for particular loan
*/
getSavingsNotes(savingAccountId: string): Observable<any> {
return this.http.get(`/savings/${savingAccountId}/notes`);
}
/**
* Adds a note to the particular Savings Id
* @param savingAccountId Savings ID
* @param noteData Note Data to be added
* @returns {Observable<any>}
*/
createSavingsNote(savingAccountId: string, noteData: any): Observable<any> {
return this.http.post(`/savings/${savingAccountId}/notes`, noteData);
}
/**
* Edits the Savings Note
* @param savingAccountId Savings ID
* @param noteId Note ID
* @param noteData Note Data
*/
editSavingsNote(savingAccountId: string, noteId: string, noteData: any) {
return this.http.put(`/savings/${savingAccountId}/notes/${noteId}`, noteData);
}
/**
* Deletes the particular Note
* @param savingAccountId Savings ID
* @param noteId Note ID
*/
deleteSavingsNote(savingAccountId: string, noteId: string) {
return this.http.delete(`/savings/${savingAccountId}/notes/${noteId}`);
}
/**
* @param savingAccountId Savings Account Id of account to get data for.
* @returns {Observable<any>} Savings data.
*/
getSavingsDocuments(savingAccountId: any): Observable<any> {
return this.http.get(`/savings/${savingAccountId}/documents`);
}
downloadSavingsDocument(parentEntityId: string, documentId: string) {
return this.http.get(`/savings/${parentEntityId}/documents/${documentId}/attachment`, { responseType: 'blob' });
}
deleteSavingsDocument(savingAccountId: any, documentId: any): Observable<any> {
return this.http.delete(`/savings/${savingAccountId}/documents/${documentId}`);
}
loadSavingsDocument(savingAccountId: any, data: any): Observable<any> {
return this.http.post(`/savings/${savingAccountId}/documents`, data);
}
}