Merge pull request #1591 from josehernandezfintecheandomx/enhancement/loan_transaction_external_id
Loan transactions using external identifer
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Loan Term</mat-label>
|
||||
<input matInput required formControlName="loanTermFrequency">
|
||||
<input type="number" matInput required formControlName="loanTermFrequency">
|
||||
<mat-error *ngIf="loansAccountTermsForm.controls.loanTermFrequency.hasError('required')">
|
||||
Loan Term is <strong>required</strong>
|
||||
</mat-error>
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>External Id</mat-label>
|
||||
<input matInput formControlName="externalId">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Payment Type</mat-label>
|
||||
<mat-select formControlName="paymentTypeId">
|
||||
|
||||
@@ -66,6 +66,7 @@ export class DisburseComponent implements OnInit {
|
||||
this.disbursementLoanForm = this.formBuilder.group({
|
||||
'actualDisbursementDate': [new Date(), Validators.required],
|
||||
'transactionAmount': ['', Validators.required],
|
||||
'externalId': '',
|
||||
'paymentTypeId': '',
|
||||
'note': ''
|
||||
});
|
||||
|
||||
+6
-1
@@ -21,12 +21,17 @@
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Transaction Amount</mat-label>
|
||||
<input matInput required formControlName="transactionAmount">
|
||||
<input type="number" matInput required formControlName="transactionAmount">
|
||||
<mat-error *ngIf="repaymentLoanForm.controls.transactionAmount.hasError('required')">
|
||||
Transaction Amount <strong>is required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>External Id</mat-label>
|
||||
<input matInput formControlName="externalId">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Payment Type</mat-label>
|
||||
<mat-select formControlName="paymentTypeId">
|
||||
|
||||
+1
@@ -65,6 +65,7 @@ export class MakeRepaymentComponent implements OnInit {
|
||||
this.repaymentLoanForm = this.formBuilder.group({
|
||||
'transactionDate': [new Date(), Validators.required],
|
||||
'transactionAmount': ['', Validators.required],
|
||||
'externalId': '',
|
||||
'paymentTypeId': '',
|
||||
'note': ''
|
||||
});
|
||||
|
||||
+6
-1
@@ -21,7 +21,7 @@
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Transaction Amount</mat-label>
|
||||
<input matInput required formControlName="transactionAmount">
|
||||
<input type="number" matInput required formControlName="transactionAmount">
|
||||
<mat-error *ngIf="prepayLoanForm.controls.transactionAmount.hasError('required')">
|
||||
Transaction Amount <strong>is required</strong>
|
||||
</mat-error>
|
||||
@@ -40,6 +40,11 @@
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>External Id</mat-label>
|
||||
<input matInput formControlName="externalId">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Payment Type</mat-label>
|
||||
<mat-select formControlName="paymentTypeId">
|
||||
|
||||
@@ -72,6 +72,7 @@ export class PrepayLoanComponent implements OnInit {
|
||||
'transactionAmount': ['', Validators.required],
|
||||
'principal': [{value: '', disabled: true}],
|
||||
'interestAmount': [{value: '', disabled: true}, Validators.required],
|
||||
'externalId': [''],
|
||||
'paymentTypeId': [''],
|
||||
'note': ['']
|
||||
});
|
||||
|
||||
@@ -33,9 +33,11 @@
|
||||
<h3> Loan Account OverView </h3>
|
||||
<span>Current Balance: {{loanDetailsData.currency.displaySymbol}}
|
||||
{{loanDetailsData.summary.totalOutstanding | number}}</span><br>
|
||||
<span>Arrears By: {{loanDetailsData.summary.totalOverdue | number}}
|
||||
<span *ngIf="loanDetailsData.inArrears">Arrears By: {{loanDetailsData.summary.totalOverdue | number}}
|
||||
<span *ngIf="!(loanDetailsData.summary.totalOverdue>=0)">Not Provided</span>
|
||||
</span><br>
|
||||
<span *ngIf="loanDetailsData.inArrears">Arrears Since: {{loanDetailsData.summary.overdueSinceDate | dateFormat}}
|
||||
</span><br>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.officeName }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="externalId">
|
||||
<th mat-header-cell *matHeaderCellDef> External Id </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)">
|
||||
<mifosx-external-identifier externalId="{{transaction.externalId}}"></mifosx-external-identifier>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="transactionDate">
|
||||
<th mat-header-cell *matHeaderCellDef> Transaction Date </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.date | dateFormat }} </td>
|
||||
@@ -33,38 +40,38 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef> Amount </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.amount | number }} </td>
|
||||
<th mat-header-cell class="center" *matHeaderCellDef> Amount </th>
|
||||
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.amount | number }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="principal">
|
||||
<th mat-header-cell *matHeaderCellDef> Breakdown </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.principalPortion | number }} </td>
|
||||
<th mat-header-cell class="center" *matHeaderCellDef> Breakdown </th>
|
||||
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.principalPortion | number }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="interest">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.interestPortion | number }} </td>
|
||||
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.interestPortion | number }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="fee">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.feeChargesPortion | number }} </td>
|
||||
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.feeChargesPortion | number }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="penalties">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.penaltyChargesPortion | number }} </td>
|
||||
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.penaltyChargesPortion | number }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="loanBalance">
|
||||
<th mat-header-cell *matHeaderCellDef> Loan Balance </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.outstandingLoanBalance | number }} </td>
|
||||
<th mat-header-cell class="r-amount" *matHeaderCellDef> Loan Balance </th>
|
||||
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.outstandingLoanBalance | number }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)">
|
||||
<th mat-header-cell class="center" *matHeaderCellDef> Actions </th>
|
||||
<td mat-cell *matCellDef="let transaction" class="center td-min-space">
|
||||
<button class="account-action-button" *ngIf="!transaction.manuallyReversed" mat-raised-button color="primary" (click)="routeEdit($event)"
|
||||
[routerLink]="[transaction.id, 'reciept']" matTooltip="View Receipts">
|
||||
<i class="fa fa-file-text"></i>
|
||||
@@ -78,27 +85,27 @@
|
||||
|
||||
<!-- Sub header -->
|
||||
<ng-container matColumnDef="header">
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="5"> </th>
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="6"> </th>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="header-principal">
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> Principal </th>
|
||||
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="1"> Principal </th>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="header-interest">
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> Interest </th>
|
||||
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="1"> Interest </th>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="header-fees">
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> Fees </th>
|
||||
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="1"> Fees </th>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="header-penalties">
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> Penalties </th>
|
||||
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="1"> Penalties </th>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="header-action">
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="2"> </th>
|
||||
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> </th>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.account-action-button{
|
||||
min-width: 26px;
|
||||
padding: 0 0 3px 0;
|
||||
margin: 0 10%;
|
||||
margin: 0 2%;
|
||||
line-height: 25px;
|
||||
}
|
||||
.select-row:hover {
|
||||
@@ -32,3 +32,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.td-min-space {
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export class TransactionsTabComponent implements OnInit {
|
||||
/** Stores the status of the loan account */
|
||||
status: string;
|
||||
/** Columns to be displayed in original schedule table. */
|
||||
displayedColumns: string[] = ['id', 'office', 'transactionDate', 'transactionType', 'amount', 'principal', 'interest', 'fee', 'penalties', 'loanBalance', 'actions'];
|
||||
displayedColumns: string[] = ['id', 'office', 'externalId', 'transactionDate', 'transactionType', 'amount', 'principal', 'interest', 'fee', 'penalties', 'loanBalance', 'actions'];
|
||||
|
||||
/**
|
||||
* Retrieves the loans with associations data from `resolve`.
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>External Id</mat-label>
|
||||
<input matInput formControlName="externalId">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Payment Type</mat-label>
|
||||
<mat-select formControlName="paymentTypeId">
|
||||
|
||||
@@ -70,6 +70,7 @@ export class EditTransactionComponent implements OnInit {
|
||||
this.editTransactionForm.patchValue({
|
||||
'transactionDate': this.transactionTemplateData.date && new Date(this.transactionTemplateData.date),
|
||||
'transactionAmount': this.transactionTemplateData.amount,
|
||||
'externalId': this.transactionTemplateData.externalId,
|
||||
'paymentTypeId': this.transactionTemplateData.paymentTypeId
|
||||
});
|
||||
}
|
||||
@@ -81,6 +82,7 @@ export class EditTransactionComponent implements OnInit {
|
||||
this.editTransactionForm = this.formBuilder.group({
|
||||
'transactionDate': ['', Validators.required],
|
||||
'transactionAmount': ['', Validators.required],
|
||||
'externalId': [''],
|
||||
'paymentTypeId': [''],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,6 +76,14 @@
|
||||
{{ transactionData.amount | currency:transactionData.currency.code }} {{ transactionData.currency.code }}
|
||||
</div>
|
||||
|
||||
<div fxFlex="50%" class="mat-body-strong" *ngIf="transactionData.externalId">
|
||||
{{ 'External Id' | translate }}
|
||||
</div>
|
||||
|
||||
<div fxFlex="50%" *ngIf="transactionData.externalId">
|
||||
{{ transactionData.externalId }}
|
||||
</div>
|
||||
|
||||
<mat-divider *ngIf="existTransactionRelations" [inset]="true"></mat-divider>
|
||||
|
||||
<div fxFlex="100%" class="mat-body-strong" *ngIf="existTransactionRelations">
|
||||
|
||||
+16
-4
@@ -66,17 +66,20 @@ export class ViewTransactionComponent implements OnInit {
|
||||
private organizationService: OrganizationService) {
|
||||
this.route.data.subscribe((data: { loansAccountTransaction: any }) => {
|
||||
this.transactionData = data.loansAccountTransaction;
|
||||
this.allowEdition = !this.transactionData.manuallyReversed && !(this.transactionData.type.id === 20 || this.transactionData.type.id === 21 || this.transactionData.type.id === 22
|
||||
|| this.transactionData.type.id === 23);
|
||||
this.allowEdition = !this.transactionData.manuallyReversed && !this.allowTransactionEdition(this.transactionData.type.id);
|
||||
this.allowUndo = !this.transactionData.manuallyReversed;
|
||||
this.allowChargeback = this.transactionData.type.repayment;
|
||||
let transactionsChargebackRelated = false;
|
||||
if (this.transactionData.type.repayment) {
|
||||
if (this.transactionData.transactionRelations) {
|
||||
this.transactionRelations.data = this.transactionData.transactionRelations;
|
||||
this.existTransactionRelations = (this.transactionData.transactionRelations.length > 0);
|
||||
let amountRelations = 0;
|
||||
this.transactionData.transactionRelations.forEach((relation: any) => {
|
||||
amountRelations += relation.amount;
|
||||
if (relation.relationType === 'CHARGEBACK') {
|
||||
amountRelations += relation.amount;
|
||||
transactionsChargebackRelated = true;
|
||||
}
|
||||
});
|
||||
this.amountRelationsAllowed = this.transactionData.amount - amountRelations;
|
||||
this.isFullRelated = (this.amountRelationsAllowed === 0);
|
||||
@@ -86,7 +89,7 @@ export class ViewTransactionComponent implements OnInit {
|
||||
if (!this.allowChargeback) {
|
||||
this.allowEdition = false;
|
||||
}
|
||||
if (this.existTransactionRelations) {
|
||||
if (this.existTransactionRelations && transactionsChargebackRelated) {
|
||||
this.allowUndo = false;
|
||||
}
|
||||
});
|
||||
@@ -103,6 +106,15 @@ export class ViewTransactionComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow edit, undo and chargeback actions
|
||||
*/
|
||||
allowTransactionEdition(transactionType: number): boolean {
|
||||
return (transactionType === 20
|
||||
|| transactionType === 21 || transactionType === 22
|
||||
|| transactionType === 23);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the loans transaction
|
||||
*/
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
<div *ngIf="loansAccountData.status.value === 'Active' && chargeData.amountOutstanding !== 0"
|
||||
fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
|
||||
<button mat-raised-button color="accent" *mifosxHasPermission="'PAY_SAVINGSACCOUNTCHARGE'" (click)="payCharge()">
|
||||
<fa-icon icon="dollar-sign"></fa-icon>
|
||||
Pay
|
||||
</button>
|
||||
<button mat-raised-button color="primary" *mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'" (click)="waiveCharge()">
|
||||
<fa-icon icon="flag"></fa-icon>
|
||||
Waive
|
||||
</button>
|
||||
<div *ngIf="loansAccountData.status.value === 'Active' && chargeData.amountOutstanding !== 0" fxLayout="row"
|
||||
fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
|
||||
<button mat-raised-button color="primary" *mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'" (click)="editCharge()">
|
||||
<fa-icon icon="flag"></fa-icon>
|
||||
Edit
|
||||
</button>
|
||||
<button mat-raised-button color="accent" *mifosxHasPermission="'PAY_SAVINGSACCOUNTCHARGE'" (click)="payCharge()">
|
||||
<fa-icon icon="dollar-sign"></fa-icon>
|
||||
Pay
|
||||
</button>
|
||||
<button mat-raised-button color="primary" *mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'" (click)="waiveCharge()">
|
||||
<fa-icon icon="flag"></fa-icon>
|
||||
Waive
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="loansAccountData.status.value === 'Submitted and pending approval'"
|
||||
fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
|
||||
<button mat-raised-button color="primary" *mifosxHasPermission="'UPDATE_SAVINGSACCOUNTCHARGE'" (click)="editCharge()">
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
Edit
|
||||
</button>
|
||||
<button mat-raised-button color="warn" *mifosxHasPermission="'DELETE_SAVINGSACCOUNTCHARGE'" (click)="deleteCharge()">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
Delete
|
||||
</button>
|
||||
<div *ngIf="loansAccountData.status.value === 'Submitted and pending approval'" fxLayout="row" fxLayoutAlign="end"
|
||||
fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
|
||||
<button mat-raised-button color="primary" *mifosxHasPermission="'UPDATE_SAVINGSACCOUNTCHARGE'" (click)="editCharge()">
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
Edit
|
||||
</button>
|
||||
<button mat-raised-button color="warn" *mifosxHasPermission="'DELETE_SAVINGSACCOUNTCHARGE'" (click)="deleteCharge()">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
@@ -67,7 +71,7 @@
|
||||
</div>
|
||||
|
||||
<div fxFlex="50%">
|
||||
{{ chargeData.dueDate | dateFormat }}
|
||||
{{ chargeData.dueDate | dateFormat }}
|
||||
</div>
|
||||
|
||||
<div fxFlex="50%" class="mat-body-strong">
|
||||
|
||||
@@ -124,6 +124,13 @@ export class ViewChargeComponent {
|
||||
value: this.chargeData.amount || this.chargeData.amountOrPercentage,
|
||||
type: 'number',
|
||||
required: true
|
||||
}),
|
||||
new DatepickerBase({
|
||||
controlName: 'dueDate',
|
||||
label: 'Due Date',
|
||||
value: new Date(this.chargeData.dueDate),
|
||||
type: 'date',
|
||||
required: true
|
||||
})
|
||||
];
|
||||
const data = {
|
||||
@@ -136,8 +143,11 @@ export class ViewChargeComponent {
|
||||
if (response.data) {
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const dueDate = this.dateUtils.formatDate(response.data.value.dueDate, dateFormat);
|
||||
const amount = response.data.value.amount;
|
||||
const dataObject = {
|
||||
...response.data.value,
|
||||
amount,
|
||||
dueDate,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user