Skip to content

Commit

Permalink
circulation: add patron circulation statistics
Browse files Browse the repository at this point in the history
This commit adds some statistics on tabs into the patron circulation
detail page. Available statistics are for 'CI/CO', 'pickup' and
'pending' tabs.

Closes rero/rero-ils#1278
Closes rero/rero-ils#1281

Authored-by: Renaud Michotte <renaud.michotte@gmail.com>
  • Loading branch information
zannkukai committed Oct 26, 2020
1 parent f5a95df commit 9c73080
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 27 deletions.
32 changes: 19 additions & 13 deletions projects/admin/src/app/circulation/patron/main/main.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,38 @@
class="nav-link"
routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}"
[routerLink]="['/circulation', 'patron', patron.patron.barcode, 'loan']"
translate
>Checkin/Checkout</a
>
[routerLink]="['/circulation', 'patron', patron.patron.barcode, 'loan']">
{{ 'Checkin/Checkout' | translate }}
<span *ngIf="this.patronCirculationStatistics.loans > 0" class="badge badge-info font-weight-normal">
{{ this.patronCirculationStatistics.loans }}
</span>
</a>
</li>
<li class="nav-item">
<a
id="pick-up-tab"
class="nav-link"
routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}"
[routerLink]="['/circulation', 'patron', patron.patron.barcode, 'pickup']"
translate
>To pick up</a
>
[routerLink]="['/circulation', 'patron', patron.patron.barcode, 'pickup']">
{{ 'To pick up' | translate }}
<span *ngIf="this.patronCirculationStatistics.pickup > 0" class="badge badge-info font-weight-normal">
{{ this.patronCirculationStatistics.pickup }}
</span>
</a>
</li>
<li class="nav-item">
<a
id="pending-tab"
class="nav-link"
routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}"
[routerLink]="['/circulation', 'patron', patron.patron.barcode, 'pending']"
translate
>Pending</a
>
[routerLink]="['/circulation', 'patron', patron.patron.barcode, 'pending']">
{{ 'Pending' | translate }}
<span *ngIf="this.patronCirculationStatistics.pending > 0" class="badge badge-info font-weight-normal">
{{ this.patronCirculationStatistics.pending }}
</span>
</a>
</li>
<li class="nav-item">
<a
Expand All @@ -84,7 +90,7 @@
routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}"
[routerLink]="['/circulation', 'patron', patron.patron.barcode, 'fees']">
{{ 'Fees' }}
{{ 'Fees' | translate }}
<span *ngIf="transactionsTotalAmount > 0" class="badge badge-warning font-weight-normal">
{{ transactionsTotalAmount | currency: organisation.default_currency }}
</span>
Expand Down
73 changes: 59 additions & 14 deletions projects/admin/src/app/circulation/patron/main/main.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, Subscription } from 'rxjs';
import { LoanState } from '../../../class/items';
import { User } from '../../../class/user';
import { OrganisationService } from '../../../service/organisation.service';
import { PatronService } from '../../../service/patron.service';
Expand All @@ -31,6 +32,16 @@ export class MainComponent implements OnInit, OnDestroy {

patron: User = undefined;

/** circulation statistics about a patron */
patronCirculationStatistics = {
loans: 0,
pickup: 0,
pending: 0,
};

/** current patron as observable */
patron$: Observable<User>;

/** the total amount of all 'open' patron transactions for the current patron */
transactionsTotalAmount = 0;

Expand All @@ -40,31 +51,65 @@ export class MainComponent implements OnInit, OnDestroy {
/** Subsription to current patron */
private _patronSubscription$: Subscription;

/** Constructor
* @param _route - ActivatedRoute
* @param _router - Router
* @param _patronService - PatronService
* @param _patronTransactionService - PatronTransactionService
* @param _organisationService - OrganisationService
*/
constructor(
private route: ActivatedRoute,
private router: Router,
private patronService: PatronService,
private patronTransactionService: PatronTransactionService,
private organisationService: OrganisationService) { }
private _route: ActivatedRoute,
private _router: Router,
private _patronService: PatronService,
private _patronTransactionService: PatronTransactionService,
private _organisationService: OrganisationService) { }

ngOnInit() {
const barcode = this.route.snapshot.paramMap.get('barcode');
this._patronSubscription$ = this.patronService.getPatron(barcode).subscribe((patron) => {
const barcode = this._route.snapshot.paramMap.get('barcode');
this._patronSubscription$ = this._patronService.getPatron(barcode).subscribe((patron) => {
if (patron) {
this.patron = patron;
this._patronTransactionSubscription$ = this.patronTransactionService.patronTransactionsSubject$.subscribe(
this._patronService.getCirculationStats(patron.pid).subscribe((stats) => this._parseStatistics(stats));
this._patronTransactionSubscription$ = this._patronTransactionService.patronTransactionsSubject$.subscribe(
(transactions) => {
this.transactionsTotalAmount = this.patronTransactionService.computeTotalTransactionsAmount(transactions);
this.transactionsTotalAmount = this._patronTransactionService.computeTotalTransactionsAmount(transactions);
}
);
this.patronTransactionService.emitPatronTransactionByPatron(patron.pid, undefined, 'open');
this._patronTransactionService.emitPatronTransactionByPatron(patron.pid, undefined, 'open');
}
});
}

/** Parse statistics from API into corresponding tab statistic.
*
* @param statistics: a dictionary of loan state/value
*/
private _parseStatistics(statistics: any) {
// reset the known stats
for (const key of Object.keys(this.patronCirculationStatistics)) {
this.patronCirculationStatistics[key] = 0;
}
// parse the stats
for (const key of Object.keys(statistics)) {
switch (key) {
case LoanState[LoanState.PENDING]:
case LoanState[LoanState.ITEM_IN_TRANSIT_FOR_PICKUP]:
this.patronCirculationStatistics.pending += statistics[key];
break;
case LoanState[LoanState.ITEM_AT_DESK]:
this.patronCirculationStatistics.pickup += statistics[key];
break;
case LoanState[LoanState.ITEM_ON_LOAN]:
this.patronCirculationStatistics.loans += statistics[key];
break;
}
}
}

clearPatron() {
this.patronService.clearPatron();
this.router.navigate(['/circulation']);
this._patronService.clearPatron();
this._router.navigate(['/circulation']);
}

ngOnDestroy() {
Expand All @@ -74,13 +119,13 @@ export class MainComponent implements OnInit, OnDestroy {
if (this._patronSubscription$) {
this._patronSubscription$.unsubscribe();
}
this.patronService.clearPatron();
this._patronService.clearPatron();
}

/** Get current organisation
* @return: current organisation
*/
get organisation() {
return this.organisationService.organisation;
return this._organisationService.organisation;
}
}
11 changes: 11 additions & 0 deletions projects/admin/src/app/service/patron.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ export class PatronService {
return this.getLoans(query, '-end_date');
}

/**
* Get circulation statistics about a patron
* @param patronPid - string : the patron pid to search
* @return Observable
*/
getCirculationStats(patronPid: string): Observable<any> {
const url = `/api/patrons/${patronPid}/circulation_stats`;
return this._http.get(url);
}

/**
* Get Loans by query
* @param query - string : Query to execute to find loans
Expand All @@ -182,4 +192,5 @@ export class PatronService {
map(hits => this._recordService.totalHits(hits.total) === 0 ? [] : hits.hits)
);
}

}

0 comments on commit 9c73080

Please sign in to comment.