fix: client charges routing and module structure (#1114)

Fixes: #1113
This commit is contained in:
Karan Takalkar
2020-07-15 19:23:57 +05:30
committed by GitHub
parent 2670137564
commit fbe0935154
18 changed files with 47 additions and 27 deletions
@@ -0,0 +1,31 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { ClientsService } from '../../../clients.service';
/**
* Client Charges data resolver.
*/
@Injectable()
export class ClientChargeOverviewResolver implements Resolve<Object> {
/**
* @param {ClientsService} ClientsService Clients service.
*/
constructor(private clientsService: ClientsService) { }
/**
* Returns the Client Charge data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const clientId = route.parent.params.clientId;
return this.clientsService.getAllClientCharges(clientId);
}
}
@@ -0,0 +1,48 @@
<div class="tab-container mat-typography">
<div style="margin-top: 5px;">
<h2> Charges Overview</h2>
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let chargeOverviewData"><i class="fa fa-stop"
[ngClass]="(!(chargeOverviewData.isWaived || chargeOverviewData.isPaid))|statusLookup"></i>
{{chargeOverviewData.name}} </td>
</ng-container>
<ng-container matColumnDef="dueAsOf">
<th mat-header-cell *matHeaderCellDef> Due as of </th>
<td mat-cell *matCellDef="let chargeOverviewData"> {{chargeOverviewData.dueDate|date}} </td>
</ng-container>
<ng-container matColumnDef="due">
<th mat-header-cell *matHeaderCellDef> Due </th>
<td mat-cell *matCellDef="let chargeOverviewData"> {{chargeOverviewData.amount}} </td>
</ng-container>
<ng-container matColumnDef="paid">
<th mat-header-cell *matHeaderCellDef> Paid </th>
<td mat-cell *matCellDef="let chargeOverviewData"> {{chargeOverviewData.amountPaid}} </td>
</ng-container>
<ng-container matColumnDef="waived">
<th mat-header-cell *matHeaderCellDef> Waived </th>
<td mat-cell *matCellDef="let chargeOverviewData"> {{chargeOverviewData.amountWaived}} </td>
</ng-container>
<ng-container matColumnDef="outstanding">
<th mat-header-cell *matHeaderCellDef> Outstanding </th>
<td mat-cell *matCellDef="let chargeOverviewData"> {{chargeOverviewData.amountOutstanding}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[10, 20, 25]" showFirstLastButtons></mat-paginator>
</div>
@@ -0,0 +1,4 @@
.tab-container {
padding: 1%;
margin: 1%;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChargesOverviewComponent } from './charges-overview.component';
describe('ChargesOverviewComponent', () => {
let component: ChargesOverviewComponent;
let fixture: ComponentFixture<ChargesOverviewComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChargesOverviewComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChargesOverviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,50 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource, MatPaginator, MatDialog } from '@angular/material';
import { ActivatedRoute } from '@angular/router';
/**
* Client Charge Overview component.
*/
@Component({
selector: 'mifosx-charges-overview',
templateUrl: './charges-overview.component.html',
styleUrls: ['./charges-overview.component.scss']
})
export class ChargesOverviewComponent implements OnInit {
/** Columns to be displayed in charge overview table. */
displayedColumns: string[] = ['name', 'dueAsOf', 'due', 'paid', 'waived', 'outstanding'];
/** Data source for charge overview table. */
dataSource: MatTableDataSource<any>;
/** Charge Overview data */
chargeOverviewData: any;
/** Paginator for charge overview table. */
@ViewChild(MatPaginator) paginator: MatPaginator;
/**
* Retrieves the charge overview data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
* @param {MatDialog} dialog Dialog reference.
*/
constructor(private route: ActivatedRoute,
public dialog: MatDialog) {
this.route.data.subscribe((data: { clientChargesData: any }) => {
this.chargeOverviewData = data.clientChargesData;
});
}
ngOnInit() {
this.setLoanClientChargeOverview();
}
/**
* Set Client Charge Overview.
*/
setLoanClientChargeOverview() {
this.dataSource = new MatTableDataSource(this.chargeOverviewData.pageItems);
this.dataSource.paginator = this.paginator;
}
}
@@ -0,0 +1,34 @@
<div class="tab-container mat-typography">
<form [formGroup]="transactionForm" (ngSubmit)="submit()">
<div fxLayout="column">
<mat-form-field>
<mat-label> Amount </mat-label>
<input matInput required autofocus formControlName="amount">
<mat-error *ngIf="transactionForm.controls.amount.hasError('required')">
Amount <strong>is required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label> Transaction date </mat-label>
<input matInput [min]="minDate" [matDatepicker]="transactionDatePicker" required formControlName="transactionDate">
<mat-datepicker-toggle matSuffix [for]="transactionDatePicker"></mat-datepicker-toggle>
<mat-datepicker #transactionDatePicker></mat-datepicker>
<mat-error *ngIf="transactionForm.controls.transactionDate.hasError('required')">
Transaction date <strong>is required</strong>
</mat-error>
</mat-form-field>
</div>
<div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../','general']">Cancel</button>
<button mat-raised-button color="primary" [disabled]="!transactionForm.valid">Submit</button>
</div>
</form>
</div>
@@ -0,0 +1,4 @@
.tab-container {
padding: 1%;
margin: 1%;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ClientPayChargesComponent } from './client-pay-charges.component';
describe('ClientPayChargesComponent', () => {
let component: ClientPayChargesComponent;
let fixture: ComponentFixture<ClientPayChargesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ClientPayChargesComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ClientPayChargesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,77 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { DatePipe } from '@angular/common';
/** Custom Services. */
import { ClientsService } from 'app/clients/clients.service';
/**
* Client Pay Charge component.
*/
@Component({
selector: 'mifosx-client-pay-charges',
templateUrl: './client-pay-charges.component.html',
styleUrls: ['./client-pay-charges.component.scss']
})
export class ClientPayChargesComponent implements OnInit {
/** Transaction Form. */
transactionForm: any;
/** Transaction Data. */
transactionData: any;
/** Minimum Date allowed. */
minDate = new Date(2000, 0, 1);
/**
* Retrieves the charge data from `resolve`.
* @param {ClientService} clientService Products Service.
* @param {FormBuilder} formBuilder Form Builder.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
*/
constructor(
private clientsService: ClientsService,
private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private datePipe: DatePipe
) {
this.route.data.subscribe((data: { transactionData: any }) => {
this.transactionData = data.transactionData;
});
}
ngOnInit() {
this.setTransactionForm();
}
/**
* Set Transaction Form.
*/
setTransactionForm() {
this.transactionForm = this.formBuilder.group({
'amount': [this.transactionData.amount, Validators.required],
'transactionDate': [new Date(), Validators.required]
});
}
/**
* Submits Transaction form.
*/
submit() {
const transactionDate = this.transactionForm.value.transactionDate;
const dateFormat = 'yyyy-MM-dd';
this.transactionForm.patchValue({
transactionDate: this.datePipe.transform(transactionDate, dateFormat)
});
const transactions = this.transactionForm.value;
transactions.locale = 'en';
transactions.dateFormat = dateFormat;
this.clientsService.payClientCharge(this.transactionData.clientId, this.transactionData.id, transactions).subscribe(() => {
this.router.navigate(['../', 'general']);
});
}
}
@@ -0,0 +1,132 @@
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
<button mat-raised-button color="primary" [routerLink]="['../../','paycharge',chargeData.id]">
<fa-icon icon="dollar-sign"></fa-icon>&nbsp;&nbsp;
Pay
</button>
<button mat-raised-button color="primary" (click)="waiveCharge()">
<i class="fa fa-flag"></i>
Waive Charge
</button>
<button mat-raised-button color="primary" (click)="deleteCharge()">
<fa-icon icon="trash"></fa-icon>&nbsp;&nbsp;
Delete
</button>
</div>
<div class="container">
<mat-card>
<mat-card-title> <i class="fa fa-stop" [ngClass]="(!(chargeData.isWaived || chargeData.isPaid))|statusLookup"></i>
{{ chargeData.name }}
</mat-card-title>
<mat-divider></mat-divider>
<mat-card-content>
<div class="share-account-tables" fxLayout="row wrap" fxFlex="50%" class="p-t-20">
<table>
<tbody>
<tr>
<td> Currency </td>
<td> {{ chargeData.currency.name }} </td>
</tr>
<tr>
<td> Charge Time Type </td>
<td> {{ chargeData.chargeTimeType.value }} </td>
</tr>
<tr>
<td> Charge Calculation Type </td>
<td> {{ chargeData.chargeCalculationType.value }} </td>
</tr>
<tr>
<td> Due as of </td>
<td> {{ chargeData.dueDate | date }} </td>
</tr>
<tr>
<td> Due </td>
<td> {{ chargeData.amount }} </td>
</tr>
<tr>
<td> Paid </td>
<td> {{ chargeData.amountPaid }} </td>
</tr>
<tr>
<td> Waived </td>
<td> {{ chargeData.amountWaived }} </td>
</tr>
<tr>
<td> Outstanding </td>
<td> {{ chargeData.amountOutstanding }} </td>
</tr>
</tbody>
</table>
</div>
</mat-card-content>
<div fxLayout="row wrap" class="content" style="padding-top:10px">
<h1><b> Transactions </b></h1>
<table mat-table [dataSource]="chargeData.clientTransactionDatas" *ngIf="chargeData.clientTransactionDatas">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> ID </th>
<td mat-cell *matCellDef="let element" [ngClass]="{'strikeoff':element.reversed}"> {{element.id}} </td>
</ng-container>
<ng-container matColumnDef="officeName">
<th mat-header-cell *matHeaderCellDef> Office Name </th>
<td mat-cell *matCellDef="let element" [ngClass]="{'strikeoff':element.reversed}"> {{element.officeName }} </td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let element" [ngClass]="{'strikeoff':element.reversed}"> {{element.type.value}} </td>
</ng-container>
<ng-container matColumnDef="transactionDate">
<th mat-header-cell *matHeaderCellDef> Transaction Date </th>
<td mat-cell *matCellDef="let element" [ngClass]="{'strikeoff':element.reversed}"> {{element.date | date}} </td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let element" [ngClass]="{'strikeoff':element.reversed}"> {{element.amount}} </td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let element" [ngClass]="{'strikeoff':element.reversed}">
<button mat-raised-button color="primary" (click)="undoTransaction(element.id)" class="delBtn">
<fa-icon icon="trash"></fa-icon>&nbsp;&nbsp;
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="viewChargeTableColumns"></tr>
<tr mat-row *matRowDef="let row; columns: viewChargeTableColumns;"></tr>
</table>
</div>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../../','general']">Back</button>
</mat-card-actions>
</mat-card>
</div>
@@ -0,0 +1,19 @@
.delBtn{
width: 20px !important;
height: 25px;
min-width: 20px!important;
line-height: 0px;
padding-left: 10px;
padding-right: 25px;
}
.strikeoff {
color: red !important;
text-decoration: line-through;
text-decoration-style: double;
}
.share-account-tables {
display: flex;
justify-content: space-between;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ViewChargeComponent } from './view-charge.component';
describe('ViewChargeComponent', () => {
let component: ViewChargeComponent;
let fixture: ComponentFixture<ViewChargeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ViewChargeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ViewChargeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,78 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { DatePipe } from '@angular/common';
import { ClientsService } from 'app/clients/clients.service';
/**
* View Charge component.
*/
@Component({
selector: 'mifosx-view-charge',
templateUrl: './view-charge.component.html',
styleUrls: ['./view-charge.component.scss']
})
export class ViewChargeComponent implements OnInit {
/** Charge Data. */
chargeData: any;
/** Mat Table Column defs. */
viewChargeTableColumns: string[] = ['id', 'officeName', 'type', 'transactionDate', 'amount', 'actions'];
/**
* Retrieves the selected job data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
*/
constructor(private route: ActivatedRoute,
private router: Router,
private date: DatePipe,
private clientService: ClientsService) {
this.route.data.subscribe((data: { clientChargeData: any }) => {
this.chargeData = data.clientChargeData;
});
}
ngOnInit() {
}
/**
* Waive Charge.
*/
waiveCharge() {
const waiveChargeObj = { clientId: this.chargeData.clientId, resourceType: this.chargeData.id};
this.clientService.waiveClientCharge(waiveChargeObj).subscribe(() => {
this.getChargeData();
});
}
/**
* Undo Transaction.
*/
undoTransaction(transactionId: any) {
const transactionData = { clientId: this.chargeData.clientId.toString(), transactionId: transactionId};
this.clientService.undoTransaction(transactionData).subscribe(() => {
this.getChargeData();
});
}
/**
* Get Charge Data.
*/
getChargeData() {
this.clientService.getSelectedChargeData(this.chargeData.clientId, this.chargeData.id).subscribe((data: any) => {
this.chargeData = data;
});
}
/**
* Delete Charge.
*/
deleteCharge() {
this.clientService.deleteCharge(this.chargeData.clientId, this.chargeData.id).subscribe(() => {
this.router.navigate(['../../clients', this.chargeData.clientId, 'general']);
});
}
}