Skip to content

Commit

Permalink
circulation: add cancel request on pending tag
Browse files Browse the repository at this point in the history
* Closes rero/rero-ils#2998.

Co-Authored-by: Bertrand Zuchuat <bertrand.zuchuat@rero.ch>
  • Loading branch information
Garfield-fr committed Apr 17, 2023
1 parent a405e64 commit 830e796
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--
RERO ILS UI
Copyright (C) 2020 RERO
Copyright (C) 2020-2023 RERO
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
Expand All @@ -25,7 +25,7 @@
</button>
<a [routerLink]="['/records', 'items', 'detail', item.pid]">{{ item.barcode }}</a>
</div>
<div class="col-6">
<div class="col-5">
<a [routerLink]="['/records', 'documents', 'detail', document.pid]" *ngIf="document.title | mainTitle as title">
{{ title }}
</a><br/>
Expand All @@ -45,6 +45,24 @@
</div>
<div class="col-2">{{ loan.created | dateTranslate: 'short' }}</div>
<div class="col-2">-<!-- TODO :: display the computed expected_date --></div>
<div class="col-1 text-right">
<ng-container *ngIf="canCancelRequest(); else noCancel">
<button type="button"
class="btn btn-outline-danger btn-sm"
(click)="showCancelRequestDialog()"
name="cancel">
<i class="fa fa-trash-o" aria-hidden="true"></i>
</button>
</ng-container>
<ng-template #noCancel>
<button type="button" class="btn btn-outline-danger btn-sm"
title="{{'The request cannot be cancelled' | translate }}"
name="cancel"
disabled>
<i class="fa fa-trash-o" aria-hidden="true"></i>
</button>
</ng-template>
</div>
<!-- SECOND ROW : item detail -->
<div class="col-12" *ngIf="!isCollapsed">
<dl class="row">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* RERO ILS UI
* Copyright (C) 2020 RERO
* Copyright (C) 2020-2023 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand All @@ -14,8 +14,12 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, Input, OnInit } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { LoanService } from '@app/admin/service/loan.service';
import { TranslateService } from '@ngx-translate/core';
import { RecordService } from '@rero/ng-core';
import { UserService } from '@rero/shared';
import { ToastrService } from 'ngx-toastr';
import { forkJoin } from 'rxjs';
import { ItemsService } from '../../../../service/items.service';

Expand All @@ -33,16 +37,26 @@ export class PendingItemComponent implements OnInit {
document = undefined;
/** detail is collapsed */
isCollapsed = true;
/** Informs parent component to remove request when it is cancelled */
@Output() cancelRequestEvent = new EventEmitter<any>();

// CONSTRUCTOR & HOOKS ======================================================
/**
* Constructor
* @param _recordService - RecordService
* @param _itemService - ItemService
* @param _translateService - TranslateService
* @param _loanService - LoanService
* @param _userService - UserService
* @param _toastrService - ToastrService
*/
constructor(
private _recordService: RecordService,
private _itemService: ItemsService
private _itemService: ItemsService,
private _translateService: TranslateService,
private _loanService: LoanService,
private _userService: UserService,
private _toastrService: ToastrService,
) { }

/** OnInit hook */
Expand All @@ -58,4 +72,31 @@ export class PendingItemComponent implements OnInit {
);
}
}

/**
* Can cancel a loan request
* @returns true if it is possible to cancel a loan
*/
canCancelRequest(): boolean {
return this._loanService.canCancelRequest(this.loan);
}

/** Show a confirmation dialog box for cancel request. */
showCancelRequestDialog(): void {
this._loanService.cancelRequestDialog().subscribe((confirm: boolean) => {
if (confirm) {
this._loanService.cancelLoan(
this.loan.metadata.item.pid,
this.loan.metadata.pid,
this._userService.user.currentLibrary
).subscribe(() => {
this._toastrService.warning(
this._translateService.instant('The pending request has been cancelled.'),
this._translateService.instant('Request')
);
this.cancelRequestEvent.emit(this.loan.id);
});
}
});
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--
RERO ILS UI
Copyright (C) 2020 RERO
Copyright (C) 2020-2023 RERO
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
Expand All @@ -19,12 +19,17 @@
<!-- HEADER -->
<div class="row p-2 mb-1 bg-dark rounded text-light">
<div class="col-2" translate>Item</div>
<div class="col-6" translate>Title</div>
<div class="col-5" translate>Title</div>
<div class="col-2" translate>Request date</div>
<div class="col-2" translate>Expected availability</div>
<div class="col-1" translate>&nbsp;</div>
</div>
<div *ngFor="let loan of loans">
<admin-pending-item [loan]="loan" class="row p-2 mb-1 border rounded align-middle"></admin-pending-item>
<admin-pending-item
class="row p-2 mb-1 border rounded align-middle"
[loan]="loan"
(cancelRequestEvent)="cancelRequest($event)"
></admin-pending-item>
</div>
</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* RERO ILS UI
* Copyright (C) 2020 RERO
* Copyright (C) 2020-2023 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand All @@ -17,6 +17,7 @@

import { Component, OnInit } from '@angular/core';
import { PatronService } from '../../../service/patron.service';
import { CirculationService } from '../../services/circulation.service';

@Component({
selector: 'admin-pending',
Expand All @@ -31,7 +32,10 @@ export class PendingComponent implements OnInit {
* Constructor
* @param _patronService - PatronService
*/
constructor(private _patronService: PatronService) {}
constructor(
private _patronService: PatronService,
private _circulationService: CirculationService
) {}

/**
* Init
Expand All @@ -46,4 +50,16 @@ export class PendingComponent implements OnInit {
}
});
}

/**
* Remove the canceled request on the loans list.
* @param loanId, the canceled loan id
*/
cancelRequest(loanId: any): void {
// Remove loan in list
const index = this.loans.findIndex((element: any) => element.id == loanId);
this.loans.splice(index, 1);
// Update count on tab
this._circulationService.circulationInformations.statistics['pending'] -= 1;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* RERO ILS UI
* Copyright (C) 2019 RERO
* Copyright (C) 2019-2023 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand All @@ -16,11 +16,10 @@
*/

import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { ItemsService } from '@app/admin/service/items.service';
import { LoanService } from '@app/admin/service/loan.service';
import { TranslateService } from '@ngx-translate/core';
import { DialogService } from '@rero/ng-core';
import { UserService } from '@rero/shared';
import { LoanState } from '@app/admin/classes/loans';
import { ItemsService } from '@app/admin/service/items.service';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

Expand All @@ -33,7 +32,7 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {
// COMPONENTS ATTRIBUTES ===============================================================
/** Loan Record */
@Input() transaction: any;
/** Ressource type */
/** Resource type */
@Input() type: string;
/** Flag for cell background */
@Input() background: boolean;
Expand All @@ -54,7 +53,7 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {
/** Pickup locations observable reference */
private _pickupLocations$: any;
/** Authorized Transaction Type to load pickup locations */
private _autorizedTypeToLoadPickupLocations = [
private _authorizedTypeToLoadPickupLocations = [
'loan_request'
];

Expand All @@ -77,20 +76,20 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {
* constructor
* @param _userService - User service
* @param _translateService - TranslateService
* @param _dialogService: DialogService
* @param _itemService: ItemsService
* @param _itemService - ItemsService
* @param _loanService - LoanService
*/
constructor(
private _userService: UserService,
private _translateService: TranslateService,
private _dialogService: DialogService,
private _itemService: ItemsService
private _itemService: ItemsService,
private _loanService: LoanService
) {}

/** OnInit hook */
ngOnInit() {
this._currentUser = this._userService.user;
if (this._autorizedTypeToLoadPickupLocations.includes(this.type)) {
if (this._authorizedTypeToLoadPickupLocations.includes(this.type)) {
this._pickupLocations$ = this.getPickupLocations().subscribe((pickups) => {
this.pickupLocations = pickups;
});
Expand All @@ -99,43 +98,32 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {

/** OnDestroy hook */
ngOnDestroy() {
if (this._autorizedTypeToLoadPickupLocations.includes(this.type)) {
if (this._authorizedTypeToLoadPickupLocations.includes(this.type)) {
this._pickupLocations$.unsubscribe();
}
}


// COMPONENT FUNCTIONS ==================================================================
/** Check if request can be cancelled. */
/**
* Check if request can be cancelled.
* @returns true if it is possible to cancel a loan
*/
canCancelRequest(): boolean {
// No permission API in backend
// Allowed when loan state is PENDING or ITEM_IN_TRANSIT_FOR_PICKUP according to actions.md
const itemStatus = [LoanState.PENDING, LoanState.ITEM_IN_TRANSIT_FOR_PICKUP, LoanState.ITEM_AT_DESK];
return itemStatus.some((element) => element === this.transaction.metadata.state);

return this._loanService.canCancelRequest(this.transaction);
}

/** Check if request pickup location can be changed. */
/**
* Check if request pickup location can be changed.
* @returns true if it is possible to update pickup location.
*/
canUpdateRequestPickupLocation(): boolean {
// No permission API in backend
// Allowed when loan state is PENDING or ITEM_IN_TRANSIT_FOR_PICKUP according to actions.md
const itemStatus = [LoanState.PENDING, LoanState.ITEM_IN_TRANSIT_FOR_PICKUP];
return itemStatus.some((element) => element === this.transaction.metadata.state);
return this._loanService.canUpdateRequestPickupLocation(this.transaction);
}

/** Show a confirmation dialog box for cancel request. */
showCancelRequestDialog(): void {
const config = {
ignoreBackdropClick: true,
initialState: {
title: this._translateService.instant('Cancel request'),
body: this._translateService.instant('Do you really want to delete this request?'),
confirmButton: true,
cancelTitleButton: this._translateService.instant('No'),
confirmTitleButton: this._translateService.instant('Yes')
}
};
this._dialogService.show(config).subscribe((confirm: boolean) => {
this._loanService.cancelRequestDialog().subscribe((confirm: boolean) => {
if (confirm) {
this.emitCancelRequest();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export class ItemTransactionsComponent implements OnInit {
.subscribe((itemData: any) => {
const status = this._translateService.instant(itemData.status);
this._toastrService.warning(
this._translateService.instant('The item is {{ status }}', { status }),
this._translateService.instant('The pending request has been cancelled.'),
this._translateService.instant('Request')
);
this.cancelRequestEvent.emit();
Expand Down
4 changes: 3 additions & 1 deletion projects/admin/src/app/service/loan.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { LoanService } from './loan.service';
import { RecordModule } from '@rero/ng-core';


describe('LoanService', () => {
beforeEach(() => TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
TranslateModule.forRoot()
TranslateModule.forRoot(),
RecordModule
]
}));

Expand Down
Loading

0 comments on commit 830e796

Please sign in to comment.