Savings account transaction with datatables (#1858)

Co-authored-by: Jose Alberto Hernandez <alberto@blue-daemon.local>
This commit is contained in:
José Alberto Hernández
2023-09-02 16:28:01 -06:00
committed by GitHub
co-authored by Jose Alberto Hernandez
parent a1b39fbb0d
commit 2bdcb69366
35 changed files with 777 additions and 623 deletions
@@ -26,7 +26,7 @@ export class SavingsAccountTransactionResolver implements Resolve<Object> {
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const savingAccountId = route.parent.paramMap.get('savingAccountId');
const transactionId = route.paramMap.get('id');
const transactionId = route.parent.paramMap.get('id');
return this.savingsService.getSavingsAccountTransaction(savingAccountId, transactionId);
}
@@ -44,12 +44,17 @@
<td mat-cell class="r-amount" *matCellDef="let transaction"> {{ transaction.runningBalance | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="viewReciept">
<th mat-header-cell class="center" *matHeaderCellDef> View Reciept </th>
<ng-container matColumnDef="actions">
<th mat-header-cell class="center" *matHeaderCellDef> Actions </th>
<td mat-cell class="center" *matCellDef="let transaction">
<button class="account-action-button" mat-raised-button color="primary" (click)="routeEdit($event)" [routerLink]="[transaction.id, 'reciept']">
<i class="fa fa-file" matTooltip="View Reciept"></i>
</button>
<button class="account-action-button" mat-raised-button color="primary" matTooltip="View Journal Entries"
matTooltipPosition="left" (click)="routeEdit($event)"
[routerLink]="['/','journal-entry', 'view', 'S'+transaction.id ]">
<i class="fa fa-arrow-circle-right"></i>
</button>
</td>
</ng-container>
@@ -20,7 +20,7 @@ export class TransactionsTabComponent implements OnInit {
/** Transactions Data */
transactionsData: any;
/** Columns to be displayed in transactions table. */
displayedColumns: string[] = ['id', 'date', 'transactionType', 'debit', 'credit', 'balance', 'viewReciept'];
displayedColumns: string[] = ['id', 'date', 'transactionType', 'debit', 'credit', 'balance', 'actions'];
/** Data source for transactions table. */
dataSource: MatTableDataSource<any>;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@@ -75,7 +75,7 @@ export class TransactionsTabComponent implements OnInit {
if (transactionsData.transfer) {
this.router.navigate([`account-transfers/account-transfers/${transactionsData.transfer.id}`], { relativeTo: this.route });
} else {
this.router.navigate([transactionsData.id], { relativeTo: this.route });
this.router.navigate([transactionsData.id, 'general'], { relativeTo: this.route });
}
}
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SavingsTransactionDatatableTabComponent } from './savings-transaction-datatable-tab.component';
describe('SavingsTransactionDatatableTabComponent', () => {
let component: SavingsTransactionDatatableTabComponent;
let fixture: ComponentFixture<SavingsTransactionDatatableTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SavingsTransactionDatatableTabComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(SavingsTransactionDatatableTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'mifosx-savings-transaction-datatable-tab',
templateUrl: './savings-transaction-datatable-tab.component.html',
styleUrls: ['./savings-transaction-datatable-tab.component.scss']
})
export class SavingsTransactionDatatableTabComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
@@ -0,0 +1,90 @@
<div fxLayoutAlign="end" class="container m-b-20" fxLayoutGap="2%"
*ngIf="!(transactionData.interestedPostedAsOn === false && (transactionData.transactionType.id === 17 || transactionData.transactionType.id === 3))">
<span *mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'">
<button mat-raised-button color="primary" *ngIf="transactionData.transactionType.value == 'Transfer' || transactionData.reversed == 'true'
|| transactionData.transactionType.id==3 || transactionData.transactionType.id==17" [routerLink]="'edit'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>Edit
</button>
</span>
<span *ngIf="!transactionData.reversed && transactionData.transactionType.amountHold">
<button mat-raised-button color="primary" *mifosxHasPermission="'RELEASEAMOUNT_SAVINGSACCOUNT'"
(click)="releaseAmount()">
<fa-icon icon="lock-open" class="m-r-10"></fa-icon>Release Amount
</button>
</span>
<button mat-raised-button color="warn" *mifosxHasPermission="'UNDOTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction()" [disabled]="transactionData.reversed">
<fa-icon icon="undo" class="m-r-10"></fa-icon>Undo
</button>
</div>
<div class="container">
<mat-card>
<mat-card-content>
<div fxLayout="row wrap" class="content">
<div fxFlex="50%" class="mat-body-strong">
Transaction Id
</div>
<div fxFlex="50%">
{{ transactionData.id }}
</div>
<div fxFlex="50%" class="mat-body-strong">
Type
</div>
<div fxFlex="50%">
{{ transactionData.transactionType.value }}
</div>
<div fxFlex="50%" class="mat-body-strong">
Transaction Date
</div>
<div fxFlex="50%">
{{ transactionData.date | dateFormat }}
</div>
<div fxFlex="50%" class="mat-body-strong">
Currency
</div>
<div fxFlex="50%">
{{ transactionData.currency.name }}
</div>
<div fxFlex="50%" class="mat-body-strong">
Amount
</div>
<div fxFlex="50%">
{{ transactionData.amount | currency }} {{ transactionData.currency.code }}
</div>
<div fxFlex="50%" class="mat-body-strong">
Note
</div>
<div fxFlex="50%">
{{ transactionData.note }}
</div>
<mifosx-transaction-payment-detail *ngIf="transactionData.paymentDetailData"
[paymentDetailData]="transactionData.paymentDetailData">
</mifosx-transaction-payment-detail>
</div>
<div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="2%" fxLayout.lt-md="column">
<button type="button" mat-raised-button color="primary" [routerLink]="['../']">{{ 'Back' | translate }}</button>
</div>
</mat-card-content>
</mat-card>
</div>
@@ -0,0 +1,14 @@
.container {
max-width: 37rem;
.content {
div {
margin: 1rem 0;
word-wrap: break-word;
}
mifosx-transaction-payment-detail {
width: 100%;
margin-bottom: 20px;
}
}
}
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SavingsTransactionGeneralTabComponent } from './savings-transaction-general-tab.component';
describe('SavingsTransactionGeneralTabComponent', () => {
let component: SavingsTransactionGeneralTabComponent;
let fixture: ComponentFixture<SavingsTransactionGeneralTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SavingsTransactionGeneralTabComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(SavingsTransactionGeneralTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,67 @@
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { Dates } from 'app/core/utils/dates';
import { ReleaseAmountDialogComponent } from 'app/savings/savings-account-view/custom-dialogs/release-amount-dialog/release-amount-dialog.component';
import { UndoTransactionDialogComponent } from 'app/savings/savings-account-view/custom-dialogs/undo-transaction-dialog/undo-transaction-dialog.component';
import { SavingsService } from 'app/savings/savings.service';
import { SettingsService } from 'app/settings/settings.service';
@Component({
selector: 'mifosx-savings-transaction-general-tab',
templateUrl: './savings-transaction-general-tab.component.html',
styleUrls: ['./savings-transaction-general-tab.component.scss']
})
export class SavingsTransactionGeneralTabComponent implements OnInit {
accountId: string;
transactionId: string;
transactionData: any;
constructor(private savingsService: SavingsService,
private route: ActivatedRoute,
private dateUtils: Dates,
private router: Router,
public dialog: MatDialog,
private settingsService: SettingsService) {
this.route.data.subscribe((data: { savingsAccountTransaction: any }) => {
this.accountId = this.route.parent.snapshot.params['savingAccountId'];
this.transactionData = data.savingsAccountTransaction;
});
}
ngOnInit(): void {
}
releaseAmount(): void {
const releaseAmountDialogRef = this.dialog.open(ReleaseAmountDialogComponent);
releaseAmountDialogRef.afterClosed().subscribe((response: any) => {
if (response.confirm) {
const data = {};
this.savingsService.executeSavingsAccountTransactionsCommand(this.accountId, 'releaseAmount', data, this.transactionData.id).subscribe(() => {
this.router.navigate(['../..'], { relativeTo: this.route });
});
}
});
}
undoTransaction(): void {
const undoTransactionAccountDialogRef = this.dialog.open(UndoTransactionDialogComponent);
undoTransactionAccountDialogRef.afterClosed().subscribe((response: any) => {
if (response.confirm) {
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
const data = {
transactionDate: this.dateUtils.formatDate(this.transactionData.date && new Date(this.transactionData.date), dateFormat),
transactionAmount: 0,
dateFormat,
locale
};
this.savingsService.executeSavingsAccountTransactionsCommand(this.accountId, 'undo', data, this.transactionData.id).subscribe(() => {
this.router.navigate(['../'], { relativeTo: this.route });
});
}
});
}
}
@@ -1,110 +1,18 @@
<mat-card class="savings-account-card">
<!-- Header -->
<mat-card-header fxLayout="column" class="header">
<mat-card-title-group class="header-title-group">
<div class="profile-image-container">
<div>
<img mat-card-md-image class="profile-image" matTooltip="Savings Account"
[src]="'assets/images/savings_account_placeholder.png'">
</div>
</div>
<div class="container">
<nav mat-tab-nav-bar class="navigation-tabs">
<a mat-tab-link [routerLink]="['./general']" routerLinkActive #general="routerLinkActive"
[active]="general.isActive">
General
</a>
<ng-container *ngFor="let entityDatatable of entityDatatables">
<a mat-tab-link [routerLink]="['./datatables',entityDatatable.registeredTableName]" routerLinkActive
#datatable="routerLinkActive" [active]="datatable.isActive"
*mifosxHasPermission="'READ_' + entityDatatable.registeredTableName">
{{entityDatatable.registeredTableName}}
</a>
</ng-container>
</nav>
<div class="mat-typography account-card-title">
<mat-card-title fxLayout="row" fxLayout.lt-md="column">
<h3 fxFlex="95%">
Transaction Id : {{transactionData.id}}<span class="m-l-10">
<mifosx-account-number accountNo="{{transactionData.id}}"></mifosx-account-number>
</span>
</h3>
<div fxFlex="15%">
<button mat-raised-button color="warn" *mifosxHasPermission="'UNDOTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction()" [disabled]="transactionData.reversed">
<fa-icon icon="undo" class="m-r-10"></fa-icon>Undo
</button>
</div>
<span *mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'">
<button mat-raised-button color="primary" *ngIf="transactionData.transactionType.value === 'Transfer' || transactionData.reversed === 'true'
|| transactionData.transactionType.id===3 || transactionData.transactionType.id===17" [routerLink]="'edit'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>Edit
</button>
</span>
<span *ngIf="!transactionData.reversed && transactionData.transactionType.amountHold">
<button mat-raised-button color="primary" *mifosxHasPermission="'RELEASEAMOUNT_SAVINGSACCOUNT'"
(click)="releaseAmount()">
<fa-icon icon="lock-open" class="m-r-10"></fa-icon>Release Amount
</button>
</span>
</mat-card-title>
</div>
<router-outlet></router-outlet>
</mat-card-title-group>
</mat-card-header>
<!-- Content -->
<mat-card-content class="content">
<div class="savings-account-tables" fxLayout="row" fxLayoutGap="2%">
<div fxFlex="96%">
<h4 class="table-headers">Transaction Summary</h4>
<table>
<tbody>
<tr *ngIf="transactionData.transactionType.value">
<td>Transaction Type</td>
<td>{{transactionData.transactionType.value}}</td>
</tr>
<tr *ngIf="transactionData.date">
<td>Transaction Date</td>
<td>{{transactionData.date | dateFormat}}</td>
</tr>
<tr *ngIf="transactionData.currency.name">
<td>Currency</td>
<td>{{transactionData.currency.name}}</td>
</tr>
<tr *ngIf="transactionData.amount">
<td>Amount</td>
<td>{{transactionData.amount | currency}}</td>
</tr>
<tr *ngIf="transactionData.note">
<td>Note</td>
<td>{{transactionData.note}}</td>
</tr>
<tr *ngIf="transactionData.paymentDetailData.paymentType">
<td>{{ 'Payment Type' | translate }}</td>
<td>{{transactionData.paymentDetailData.paymentType.name}}</td>
</tr>
<tr *ngIf="transactionData.paymentDetailData.accountNumber">
<td>{{ 'Account Number' | translate }}</td>
<td>{{transactionData.paymentDetailData.accountNumber}}</td>
</tr>
<tr *ngIf="transactionData.paymentDetailData.checkNumber">
<td>{{ 'Cheque Number' | translate }}</td>
<td>{{transactionData.paymentDetailData.checkNumber}}</td>
</tr>
<tr *ngIf="transactionData.paymentDetailData.routingCode">
<td>{{ 'Routing Code' | translate }}</td>
<td>{{transactionData.paymentDetailData.routingCode}}</td>
</tr>
<tr *ngIf="transactionData.paymentDetailData.receiptNumber">
<td>{{ 'Receipt Number' | translate }}</td>
<td>{{transactionData.paymentDetailData.receiptNumber}}</td>
</tr>
<tr *ngIf="transactionData.paymentDetailData.bankNumber">
<td>{{ 'Bank Number' | translate }}</td>
<td>{{transactionData.paymentDetailData.bankNumber}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<nav mat-tab-nav-bar class="navigation-tabs">
<ng-container *ngFor="let transactionDatatable of entityDatatable">
<a mat-tab-link *mifosxHasPermission="'READ_' + transactionDatatable.registeredTableName"
[routerLink]="['./datatables',transactionDatatable.registeredTableName]" routerLinkActive #datatable="routerLinkActive"
[active]="datatable.isActive">
{{transactionDatatable.registeredTableName}}
</a>
</ng-container>
</nav>
<router-outlet></router-outlet>
</mat-card-content>
</mat-card>
</div>
@@ -1,54 +1,9 @@
.savings-account-card {
margin: 0 auto;
max-width: 80rem;
width: 90%;
padding: 0;
.header {
padding: 1%;
background-color:rgb(16, 116, 185);
.header-title-group {
.account-card-title {
color: white;
width: 90%;
p {
color: white;
}
}
}
.profile-image-container {
margin: 1%;
.profile-image {
object-fit: cover;
border-radius: 20px;
}
}
.account-actions {
align-self: flex-end;
margin: 0 1%;
i {
margin-bottom: 2px;
margin-right: 4px;
}
}
}
.navigation-tabs {
background-color: #f2f2f2;
overflow: auto;
}
.container {
max-width: 37rem;
.content {
.savings-account-tables {
padding: 1%;
margin: 1%;
.table-headers {
margin: 0;
padding: 6px;
}
td {
padding: 3px;
}
}
div {
margin: 1rem 0;
word-wrap: break-word;
}
}
i, img:hover {
cursor: pointer;
}
}
}
@@ -1,21 +1,8 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivatedRoute } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
import { SettingsService } from 'app/settings/settings.service';
/** Custom Dialogs */
import { UndoTransactionDialogComponent } from '../../custom-dialogs/undo-transaction-dialog/undo-transaction-dialog.component';
import { Dates } from 'app/core/utils/dates';
import { ReleaseAmountDialogComponent } from '../../custom-dialogs/release-amount-dialog/release-amount-dialog.component';
/**
* View Transaction Component.
* TODO: Add support for account transfers.
*/
@Component({
selector: 'mifosx-view-transaction',
templateUrl: './view-transaction.component.html',
@@ -28,65 +15,17 @@ export class ViewTransactionComponent {
accountId: any;
/** Transaction Data Tables */
entityDatatable: any;
/** Multi Row Datatable Flag */
multiRowDatatableFlag: boolean;
isActive: false;
entityDatatables: any;
/**
* Retrieves the Transaction data from `resolve`.
* @param {SavingsService} savingsService Savings Service
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
* @param {MatDialog} dialog Dialog reference.
* @param {Dates} dateUtils Date Utils.
* @param {SettingsService} settingsService Setting service
*/
constructor(private savingsService: SavingsService,
private route: ActivatedRoute,
private dateUtils: Dates,
private router: Router,
public dialog: MatDialog,
private settingsService: SettingsService) {
this.route.data.subscribe((data: { savingsAccountTransaction: any, transactionDatatables: any}) => {
constructor(private route: ActivatedRoute,
public dialog: MatDialog) {
this.route.data.subscribe((data: { transactionDatatables: any}) => {
this.accountId = this.route.snapshot.params['savingAccountId'];
this.transactionData = data.savingsAccountTransaction;
this.entityDatatable = data.transactionDatatables;
this.entityDatatables = data.transactionDatatables;
});
}
/**
* Undo the savings transaction
*/
undoTransaction() {
const undoTransactionAccountDialogRef = this.dialog.open(UndoTransactionDialogComponent);
undoTransactionAccountDialogRef.afterClosed().subscribe((response: any) => {
if (response.confirm) {
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
const data = {
transactionDate: this.dateUtils.formatDate(this.transactionData.date && new Date(this.transactionData.date), dateFormat),
transactionAmount: 0,
dateFormat,
locale
};
this.savingsService.executeSavingsAccountTransactionsCommand(this.accountId, 'undo', data, this.transactionData.id).subscribe(() => {
this.router.navigate(['../'], { relativeTo: this.route });
});
}
});
}
releaseAmount() {
const releaseAmountDialogRef = this.dialog.open(ReleaseAmountDialogComponent);
releaseAmountDialogRef.afterClosed().subscribe((response: any) => {
if (response.confirm) {
const data = { };
this.savingsService.executeSavingsAccountTransactionsCommand(this.accountId, 'releaseAmount', data, this.transactionData.id).subscribe(() => {
this.router.navigate(['../'], { relativeTo: this.route });
});
}
});
}
}
+22 -10
View File
@@ -44,6 +44,7 @@ import { SavingsDocumentsTabComponent } from './savings-account-view/savings-doc
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 { SavingsTransactionGeneralTabComponent } from './savings-account-view/transactions/view-transaction/savings-transaction-general-tab/savings-transaction-general-tab.component';
/** Savings Routes */
const routes: Routes = [
@@ -144,22 +145,33 @@ const routes: Routes = [
path: '',
component: ViewTransactionComponent,
resolve: {
savingsAccountTransaction: SavingsAccountTransactionResolver,
transactionDatatables: TransactionDatatablesResolver
},
children: [
{
path: 'datatables',
children: [{
path: ':datatableName',
component: DatatableTransactionTabComponent,
data: { title: extract('View Data table'), routeParamBreadcrumb: 'datatableName' },
resolve: {
transactionDatatable: TransactionDatatableResolver
}
path: '',
redirectTo: 'general',
pathMatch: 'full'
},
{
path: 'general',
component: SavingsTransactionGeneralTabComponent,
resolve: {
savingsAccountTransaction: SavingsAccountTransactionResolver,
}
},
{
path: 'datatables',
children: [
{
path: ':datatableName',
component: DatatableTransactionTabComponent,
data: { title: extract('View Data table'), routeParamBreadcrumb: 'datatableName' },
resolve: {
transactionDatatable: TransactionDatatableResolver
}
}
]
}
]
},
+5 -1
View File
@@ -50,6 +50,8 @@ import { ReleaseAmountDialogComponent } from './savings-account-view/custom-dial
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 { DatatableTransactionTabComponent } from './savings-account-view/transactions/view-transaction/datatable-transaction-tab/datatable-transaction-tab.component';
import { SavingsTransactionGeneralTabComponent } from './savings-account-view/transactions/view-transaction/savings-transaction-general-tab/savings-transaction-general-tab.component';
import { SavingsTransactionDatatableTabComponent } from './savings-account-view/transactions/view-transaction/savings-transaction-datatable-tab/savings-transaction-datatable-tab.component';
/**
@@ -106,7 +108,9 @@ import { DatatableTransactionTabComponent } from './savings-account-view/transac
ReleaseAmountDialogComponent,
SavingsDocumentsTabComponent,
NotesTabComponent,
DatatableTransactionTabComponent
DatatableTransactionTabComponent,
SavingsTransactionGeneralTabComponent,
SavingsTransactionDatatableTabComponent
],
providers: [ ]
})