feat(accounting): add view transactions component
Add view transactions component, ability to revert transaction and viewing journal entry details. Fixes #139
This commit is contained in:
@@ -4,6 +4,7 @@ import { Routes, RouterModule } from '@angular/router';
|
|||||||
import { Route, extract } from '../core';
|
import { Route, extract } from '../core';
|
||||||
import { AccountingComponent } from './accounting.component';
|
import { AccountingComponent } from './accounting.component';
|
||||||
import { FrequentPostingsComponent } from './frequent-postings/frequent-postings.component';
|
import { FrequentPostingsComponent } from './frequent-postings/frequent-postings.component';
|
||||||
|
import { ViewTransactionComponent } from './view-transaction/view-transaction.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
Route.withShell([
|
Route.withShell([
|
||||||
@@ -19,6 +20,17 @@ const routes: Routes = [
|
|||||||
path: 'frequent-postings',
|
path: 'frequent-postings',
|
||||||
component: FrequentPostingsComponent,
|
component: FrequentPostingsComponent,
|
||||||
data: { title: extract('Frequent Postings'), breadcrumb: 'Frequent Postings' }
|
data: { title: extract('Frequent Postings'), breadcrumb: 'Frequent Postings' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'transactions',
|
||||||
|
data: { title: extract('Transactions'), breadcrumb: 'Transactions' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'view/:id',
|
||||||
|
component: ViewTransactionComponent,
|
||||||
|
data: { title: extract('View Transaction'), routeParamBreadcrumb: 'id' }
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import { CoreModule } from '../core/core.module';
|
|||||||
import { AccountingComponent } from './accounting.component';
|
import { AccountingComponent } from './accounting.component';
|
||||||
import { AccountingRoutingModule } from './accounting-routing.module';
|
import { AccountingRoutingModule } from './accounting-routing.module';
|
||||||
import { FrequentPostingsComponent } from './frequent-postings/frequent-postings.component';
|
import { FrequentPostingsComponent } from './frequent-postings/frequent-postings.component';
|
||||||
|
import { ViewTransactionComponent } from './view-transaction/view-transaction.component';
|
||||||
|
import { RevertTransactionComponent } from './revert-transaction/revert-transaction.component';
|
||||||
|
import { ViewJournalEntryComponent } from './view-journal-entry/view-journal-entry.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -14,6 +17,16 @@ import { FrequentPostingsComponent } from './frequent-postings/frequent-postings
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
AccountingRoutingModule
|
AccountingRoutingModule
|
||||||
],
|
],
|
||||||
declarations: [AccountingComponent, FrequentPostingsComponent]
|
declarations: [
|
||||||
|
AccountingComponent,
|
||||||
|
FrequentPostingsComponent,
|
||||||
|
ViewTransactionComponent,
|
||||||
|
RevertTransactionComponent,
|
||||||
|
ViewJournalEntryComponent
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
RevertTransactionComponent,
|
||||||
|
ViewJournalEntryComponent
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class AccountingModule { }
|
export class AccountingModule { }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@@ -29,5 +29,21 @@ export class AccountingService {
|
|||||||
return this.http.post('/journalentries', journalEntry);
|
return this.http.post('/journalentries', journalEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getJournalEntry(transactionId: string) {
|
||||||
|
let httpParams = new HttpParams();
|
||||||
|
httpParams = httpParams.set('transactionId', transactionId);
|
||||||
|
httpParams = httpParams.set('transactionDetails', 'true');
|
||||||
|
return this.http.get(`/journalentries`, { params: httpParams });
|
||||||
|
}
|
||||||
|
|
||||||
|
revertTransaction(transactionId: string, comments: string) {
|
||||||
|
let httpParams = new HttpParams();
|
||||||
|
httpParams = httpParams.set('command', 'reverse');
|
||||||
|
let data = {};
|
||||||
|
if (comments) {
|
||||||
|
data = { comments: comments };
|
||||||
|
}
|
||||||
|
return this.http.post(`/journalentries/${transactionId}`, data, { params: httpParams });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<span fxFlex="48%" fxHide.lt-md></span>
|
<span fxFlex="48%" fxHide.lt-md></span>
|
||||||
|
|
||||||
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" formArrayName="debits"
|
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" formArrayName="debits"
|
||||||
*ngFor="let debit of frequentPostingsForm.get('debits').controls; let i = index;">
|
*ngFor="let debit of getFormArrayData('debits').controls; let i = index;">
|
||||||
|
|
||||||
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column" [formGroupName]="i">
|
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column" [formGroupName]="i">
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" formArrayName="credits"
|
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" formArrayName="credits"
|
||||||
*ngFor="let credit of frequentPostingsForm.get('credits').controls; let i = index;">
|
*ngFor="let credit of getFormArrayData('credits').controls; let i = index;">
|
||||||
|
|
||||||
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column" [formGroupName]="i">
|
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column" [formGroupName]="i">
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms';
|
import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { AccountingService } from '../accounting.service';
|
import { AccountingService } from '../accounting.service';
|
||||||
|
|
||||||
@@ -12,7 +13,6 @@ export class FrequentPostingsComponent implements OnInit {
|
|||||||
|
|
||||||
// TODO: Validations
|
// TODO: Validations
|
||||||
// https://github.com/openMF/incubator-fineract/blob/master/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/exception/JournalEntryInvalidException.java
|
// https://github.com/openMF/incubator-fineract/blob/master/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/exception/JournalEntryInvalidException.java
|
||||||
// TESTING: transactionId: 8b5748a57b73
|
|
||||||
|
|
||||||
minDate = new Date(2000, 0, 1);
|
minDate = new Date(2000, 0, 1);
|
||||||
maxDate = new Date();
|
maxDate = new Date();
|
||||||
@@ -28,7 +28,8 @@ export class FrequentPostingsComponent implements OnInit {
|
|||||||
allowMultipleDebitEntries: boolean;
|
allowMultipleDebitEntries: boolean;
|
||||||
|
|
||||||
constructor(private formBuilder: FormBuilder,
|
constructor(private formBuilder: FormBuilder,
|
||||||
private accountingService: AccountingService) { }
|
private accountingService: AccountingService,
|
||||||
|
private router: Router) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.createFrequentPostingsForm();
|
this.createFrequentPostingsForm();
|
||||||
@@ -84,6 +85,10 @@ export class FrequentPostingsComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFormArrayData(type: string): FormArray {
|
||||||
|
return <FormArray>this.frequentPostingsForm.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
addAffectedGLEntry(affectedGLEntryFormArray: FormArray) {
|
addAffectedGLEntry(affectedGLEntryFormArray: FormArray) {
|
||||||
affectedGLEntryFormArray.push(this.createAffectedGLEntryForm());
|
affectedGLEntryFormArray.push(this.createAffectedGLEntryForm());
|
||||||
}
|
}
|
||||||
@@ -124,8 +129,7 @@ export class FrequentPostingsComponent implements OnInit {
|
|||||||
journalEntry.dateFormat = 'dd MMMM yyyy';
|
journalEntry.dateFormat = 'dd MMMM yyyy';
|
||||||
journalEntry.transactionDate = '20 July 2018';
|
journalEntry.transactionDate = '20 July 2018';
|
||||||
this.accountingService.createJournalEntry(journalEntry).subscribe(response => {
|
this.accountingService.createJournalEntry(journalEntry).subscribe(response => {
|
||||||
console.log(response);
|
this.router.navigate(['/accounting/transactions/view', response.transactionId]);
|
||||||
// navigate to view transaction with response.transactionId
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<div *ngIf="!data.reverted; else reverted">
|
||||||
|
|
||||||
|
<h1 mat-dialog-title>Revert Transaction</h1>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<p>Are you sure you want to revert this transaction?</p>
|
||||||
|
<mat-form-field fxFlexFill>
|
||||||
|
<textarea matInput placeholder="Comments" [formControl]="comments"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<mat-dialog-actions align="end">
|
||||||
|
<button mat-button mat-dialog-close>No</button>
|
||||||
|
<button mat-button [mat-dialog-close]="{ revert: true, comments: comments.value }">Yes</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template #reverted>
|
||||||
|
|
||||||
|
<h1 mat-dialog-title>Transaction Reverted</h1>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<h4>Success!</h4>
|
||||||
|
<p>A new journal entry has been created to reverse this transaction:</p>
|
||||||
|
<p>Transaction ID: {{ data.transactionId }}</p>
|
||||||
|
</div>
|
||||||
|
<mat-dialog-actions align="end">
|
||||||
|
<button mat-button mat-dialog-close>Close</button>
|
||||||
|
<button mat-button [mat-dialog-close]="{ redirect: true }">Redirect to New Transaction</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
|
|
||||||
|
</ng-template>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RevertTransactionComponent } from './revert-transaction.component';
|
||||||
|
|
||||||
|
describe('RevertTransactionComponent', () => {
|
||||||
|
let component: RevertTransactionComponent;
|
||||||
|
let fixture: ComponentFixture<RevertTransactionComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RevertTransactionComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RevertTransactionComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Component, OnInit, Inject } from '@angular/core';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-revert-transaction',
|
||||||
|
templateUrl: './revert-transaction.component.html',
|
||||||
|
styleUrls: ['./revert-transaction.component.scss']
|
||||||
|
})
|
||||||
|
export class RevertTransactionComponent implements OnInit {
|
||||||
|
|
||||||
|
comments = new FormControl('');
|
||||||
|
|
||||||
|
constructor(public dialogRef: MatDialogRef<RevertTransactionComponent>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: any) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
<h1 mat-dialog-title>View Journal Entry</h1>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<table>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Office</th>
|
||||||
|
<td>{{ data.journalEntry.officeName }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Entry ID</th>
|
||||||
|
<td>{{ data.journalEntry.id }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Transaction ID</th>
|
||||||
|
<td>{{ data.journalEntry.transactionId }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Transaction Date</th>
|
||||||
|
<td>{{ data.journalEntry.transactionDate }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Type</th>
|
||||||
|
<td>{{ data.journalEntry.glAccountType.value }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Account Code</th>
|
||||||
|
<td>{{ data.journalEntry.glAccountId }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Account Name</th>
|
||||||
|
<td>{{ data.journalEntry.glAccountName }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<span *ngIf="data.journalEntry.entryType.value === 'CREDIT'">Credit</span>
|
||||||
|
<span *ngIf="data.journalEntry.entryType.value === 'DEBIT'">Debit</span>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
{{ (data.journalEntry.currency.displaySymbol || data.journalEntry.currency.code) + ' ' + data.journalEntry.amount }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.referenceNumber">
|
||||||
|
<th>Reference Number</th>
|
||||||
|
<td>{{ data.journalEntry.referenceNumber }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.comments">
|
||||||
|
<th>Comments</th>
|
||||||
|
<td>{{ data.journalEntry.comments }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.transactionDetails.paymentDetails">
|
||||||
|
<th colspan="2" class="header">Payment Details</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.transactionDetails.paymentDetails?.paymentType">
|
||||||
|
<th>Payment Type</th>
|
||||||
|
<td>{{ data.journalEntry.transactionDetails.paymentDetails.paymentType.name }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.transactionDetails.paymentDetails?.accountNumber">
|
||||||
|
<th>Account Number</th>
|
||||||
|
<td>{{ data.journalEntry.transactionDetails.paymentDetails.accountNumber }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.transactionDetails.paymentDetails?.checkNumber">
|
||||||
|
<th>Cheque Number</th>
|
||||||
|
<td>{{ data.journalEntry.transactionDetails.paymentDetails.checkNumber }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.transactionDetails.paymentDetails?.routingCode">
|
||||||
|
<th>Routing Code</th>
|
||||||
|
<td>{{ data.journalEntry.transactionDetails.paymentDetails.routingCode }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.transactionDetails.paymentDetails?.receiptNumber">
|
||||||
|
<th>Receipt Number</th>
|
||||||
|
<td>{{ data.journalEntry.transactionDetails.paymentDetails.receiptNumber }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr *ngIf="data.journalEntry.transactionDetails.paymentDetails?.bankNumber">
|
||||||
|
<th>Bank Number</th>
|
||||||
|
<td>{{ data.journalEntry.transactionDetails.paymentDetails.bankNumber }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Created by</th>
|
||||||
|
<td>{{ data.journalEntry.createdByUserName }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Created on</th>
|
||||||
|
<td>{{ data.journalEntry.createdDate }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<mat-dialog-actions align="end">
|
||||||
|
<button mat-button mat-dialog-close>Close</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 0 0.4rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.4rem 0.4rem 0 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ViewJournalEntryComponent } from './view-journal-entry.component';
|
||||||
|
|
||||||
|
describe('ViewJournalEntryComponent', () => {
|
||||||
|
let component: ViewJournalEntryComponent;
|
||||||
|
let fixture: ComponentFixture<ViewJournalEntryComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ViewJournalEntryComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ViewJournalEntryComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Component, OnInit, Inject } from '@angular/core';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-view-journal-entry',
|
||||||
|
templateUrl: './view-journal-entry.component.html',
|
||||||
|
styleUrls: ['./view-journal-entry.component.scss']
|
||||||
|
})
|
||||||
|
export class ViewJournalEntryComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor(public dialogRef: MatDialogRef<ViewJournalEntryComponent>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: any) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<div fxLayout="row" fxLayoutAlign="end" class="container m-b-20">
|
||||||
|
<button mat-raised-button color="primary" (click)="revertTransaction()" [disabled]="dataSource?.data[0].reversed">
|
||||||
|
<span *ngIf="!dataSource?.data[0].reversed"><mat-icon>undo</mat-icon> Revert Transaction</span>
|
||||||
|
<span *ngIf="dataSource?.data[0].reversed">Transaction Reverted</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container m-b-20">
|
||||||
|
|
||||||
|
<mat-card class="mat-elevation-z8" *ngIf="dataSource">
|
||||||
|
|
||||||
|
<mat-card-content>
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" class="content">
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%" class="header">
|
||||||
|
Office
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%">
|
||||||
|
{{ dataSource.data[0].officeName }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%" class="header">
|
||||||
|
Transaction Date
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%">
|
||||||
|
{{ dataSource.data[0].transactionDate }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%" class="header">
|
||||||
|
Created By
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%">
|
||||||
|
{{ dataSource.data[0].createdByUserName }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%" class="header">
|
||||||
|
Created On
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlex="25%" fxFlex.lt-md="50%">
|
||||||
|
{{ dataSource.data[0].createdDate }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-card-content>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mat-elevation-z8 container">
|
||||||
|
|
||||||
|
<table mat-table [dataSource]="dataSource" matSort>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="id">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Entry ID </th>
|
||||||
|
<td mat-cell *matCellDef="let transaction"> {{ transaction.id }} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="glAccountType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Type </th>
|
||||||
|
<td mat-cell *matCellDef="let transaction"> {{ transaction.glAccountType.value }} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="glAccountCode">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Account Code </th>
|
||||||
|
<td mat-cell *matCellDef="let transaction"> {{ transaction.glAccountCode }} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="glAccountName">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Account Name </th>
|
||||||
|
<td mat-cell *matCellDef="let transaction"> {{ transaction.glAccountName }} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="debit">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Debit </th>
|
||||||
|
<td mat-cell *matCellDef="let transaction"><span *ngIf="transaction.entryType.value === 'DEBIT'"> {{ (transaction.currency.displaySymbol || transaction.currency.code) + ' ' + transaction.amount }} </span></td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="credit">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Credit </th>
|
||||||
|
<td mat-cell *matCellDef="let transaction"><span *ngIf="transaction.entryType.value === 'CREDIT'"> {{ (transaction.currency.displaySymbol || transaction.currency.code) + ' ' + transaction.amount }} </span></td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="viewJournalEntry(row)" class="select"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<mat-paginator [pageSizeOptions]="[5, 10]" showFirstLastButtons></mat-paginator>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
.content {
|
||||||
|
div {
|
||||||
|
line-height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ViewTransactionComponent } from './view-transaction.component';
|
||||||
|
|
||||||
|
describe('ViewTransactionComponent', () => {
|
||||||
|
let component: ViewTransactionComponent;
|
||||||
|
let fixture: ComponentFixture<ViewTransactionComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ViewTransactionComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ViewTransactionComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||||
|
import { MatDialog, MatSort, MatPaginator, MatTableDataSource } from '@angular/material';
|
||||||
|
|
||||||
|
import { AccountingService } from '../accounting.service';
|
||||||
|
import { RevertTransactionComponent } from '../revert-transaction/revert-transaction.component';
|
||||||
|
import { ViewJournalEntryComponent } from '../view-journal-entry/view-journal-entry.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-view-transaction',
|
||||||
|
templateUrl: './view-transaction.component.html',
|
||||||
|
styleUrls: ['./view-transaction.component.scss']
|
||||||
|
})
|
||||||
|
export class ViewTransactionComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
// TODO: Update once language and date settings are setup
|
||||||
|
transactionId: string;
|
||||||
|
transactionId$: any;
|
||||||
|
displayedColumns: string[] = ['id', 'glAccountType', 'glAccountCode', 'glAccountName', 'debit', 'credit'];
|
||||||
|
dataSource: any;
|
||||||
|
|
||||||
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
|
@ViewChild(MatSort) sort: MatSort;
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private accountingService: AccountingService,
|
||||||
|
public dialog: MatDialog) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.transactionId$ = this.route.paramMap.subscribe((params: ParamMap) => {
|
||||||
|
this.transactionId = params.get('id');
|
||||||
|
this.getJournalEntry();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getJournalEntry() {
|
||||||
|
this.accountingService.getJournalEntry(this.transactionId).subscribe((journalEntry: any) => {
|
||||||
|
this.dataSource = new MatTableDataSource(journalEntry.pageItems);
|
||||||
|
this.dataSource.paginator = this.paginator;
|
||||||
|
this.dataSource.sortingDataAccessor = (transaction: any, property: any) => {
|
||||||
|
switch (property) {
|
||||||
|
case 'glAccountType': return transaction.glAccountType.value;
|
||||||
|
case 'debit': return transaction.amount;
|
||||||
|
case 'credit': return transaction.amount;
|
||||||
|
default: return transaction[property];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.dataSource.sort = this.sort;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
viewJournalEntry(journalEntry: any) {
|
||||||
|
this.dialog.open(ViewJournalEntryComponent, {
|
||||||
|
data: { journalEntry: journalEntry }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
revertTransaction(transactionId?: string) {
|
||||||
|
const revertTransactionDialogRef = this.dialog.open(RevertTransactionComponent, {
|
||||||
|
data: { reverted: this.dataSource.data[0].reversed, transactionId: transactionId }
|
||||||
|
});
|
||||||
|
revertTransactionDialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.revert) {
|
||||||
|
this.accountingService.revertTransaction(this.transactionId, response.comments).subscribe((reversedTransaction: any) => {
|
||||||
|
this.dataSource.data[0].reversed = true;
|
||||||
|
this.revertTransaction(reversedTransaction.transactionId);
|
||||||
|
});
|
||||||
|
} else if (response.redirect) {
|
||||||
|
this.router.navigate(['/accounting/transactions/view', transactionId]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.transactionId$.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user