From 541f1f1da4d18309bb9f81254a4a49724dc29510 Mon Sep 17 00:00:00 2001 From: Bertrand Zuchuat Date: Tue, 9 Apr 2024 08:54:02 +0200 Subject: [PATCH] feat(item): add fees on item detail view * Adds fees on item detail view. * Changes patron link on fees brief view to redirect to the patron circulation fees tab. * Closes rero/rero-ils#3578. Co-Authored-by: Bertrand Zuchuat --- .../app/api/patron-transaction-api.service.ts | 13 +++- projects/admin/src/app/app.module.ts | 15 ++--- ...n-transaction-event-overdue.component.html | 6 +- .../item-detail-view.component.html | 5 ++ .../item-detail-view.component.ts | 8 +-- .../item-fees/item-fees.component.html | 45 ++++++++++++++ .../item-fees/item-fees.component.ts | 61 +++++++++++++++++++ 7 files changed, 137 insertions(+), 16 deletions(-) create mode 100644 projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.html create mode 100644 projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.ts diff --git a/projects/admin/src/app/api/patron-transaction-api.service.ts b/projects/admin/src/app/api/patron-transaction-api.service.ts index 13c45c953..de3106b2a 100644 --- a/projects/admin/src/app/api/patron-transaction-api.service.ts +++ b/projects/admin/src/app/api/patron-transaction-api.service.ts @@ -16,8 +16,8 @@ */ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApiService } from '@rero/ng-core'; -import { Observable } from 'rxjs'; +import { ApiService, Record, RecordService } from '@rero/ng-core'; +import { Observable, map } from 'rxjs'; import { FeeFormModel } from '../circulation/patron/patron-transactions/patron-fee/patron-fee.component'; @Injectable({ @@ -31,7 +31,8 @@ export class PatronTransactionApiService { */ constructor( private _httpClient: HttpClient, - private _apiService: ApiService + private _apiService: ApiService, + private recordService: RecordService ) {} /** @@ -41,4 +42,10 @@ export class PatronTransactionApiService { addFee(model: FeeFormModel): Observable { return this._httpClient.post(this._apiService.getEndpointByType('patron_transactions/'), model); } + + getActiveFeesByItemPid(itemPid: string): any { + const query = `item.pid:${itemPid} AND total_amount:>0`; + return this.recordService.getRecords('patron_transactions', query) + .pipe(map((result: Record) => result.hits.hits)); + } } diff --git a/projects/admin/src/app/app.module.ts b/projects/admin/src/app/app.module.ts index b7816e4ee..ae22e47e8 100644 --- a/projects/admin/src/app/app.module.ts +++ b/projects/admin/src/app/app.module.ts @@ -25,8 +25,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { PrimengImportModule } from '@app/admin/shared/primeng-import/primeng-import.module'; import { HotkeysModule, HotkeysService } from '@ngneat/hotkeys'; import { FormlyModule } from '@ngx-formly/core'; -import { FormlyPrimeNGModule } from '@ngx-formly/primeng'; -import { FormlyFieldSelect, FormlySelectModule } from '@ngx-formly/primeng/select'; +import { FormlyFieldSelect } from '@ngx-formly/primeng/select'; import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client'; import { TranslateLoader as BaseTranslateLoader, TranslateModule } from '@ngx-translate/core'; import { @@ -145,26 +144,29 @@ import { RelatedResourceComponent } from './record/detail-view/document-detail-v import { EntitiesLocalDetailViewComponent } from './record/detail-view/entities-detail-view/local/entities-local-detail-view.component'; import { EntitiesLocalGlobalComponent } from './record/detail-view/entities-detail-view/local/entities-local-global.component'; import { LocalOrganisationDetailViewComponent } from './record/detail-view/entities-detail-view/local/local-organisation-detail-view/local-organisation-detail-view.component'; +import { LocalPageDetailComponent } from './record/detail-view/entities-detail-view/local/local-page-detail/local-page-detail.component'; import { LocalPersonDetailViewComponent } from './record/detail-view/entities-detail-view/local/local-person-detail-view/local-person-detail-view.component'; import { LocalPlaceDetailViewComponent } from './record/detail-view/entities-detail-view/local/local-place-detail-view/local-place-detail-view.component'; import { LocalTopicDetailViewComponent } from './record/detail-view/entities-detail-view/local/local-topic-detail-view/local-topic-detail-view.component'; import { LocalWorkDetailViewComponent } from './record/detail-view/entities-detail-view/local/local-work-detail-view/local-work-detail-view.component'; import { RemoteEntitiesDetailViewComponent } from './record/detail-view/entities-detail-view/remote/entities-remote-detail-view.component'; import { RemoteEntitiesOrganisationDetailViewComponent } from './record/detail-view/entities-detail-view/remote/remote-organisation-detail-view/remote-entities-organisation-detail-view.component'; +import { RemotePageDetailComponent } from './record/detail-view/entities-detail-view/remote/remote-page-detail/remote-page-detail.component'; import { RemoteEntitiesPersonDetailViewComponent } from './record/detail-view/entities-detail-view/remote/remote-person-detail-view/remote-entities-person-detail-view.component'; import { RemoteTopicDetailViewComponent } from './record/detail-view/entities-detail-view/remote/remote-topic-detail-view/remote-topic-detail-view.component'; import { HoldingDetailViewComponent } from './record/detail-view/holding-detail-view/holding-detail-view.component'; +import { HoldingPageDetailComponent } from './record/detail-view/holding-detail-view/holding-page-detail/holding-page-detail.component'; import { ExpectedIssueComponent } from './record/detail-view/holding-detail-view/serial-holding-detail-view/expected-issue/expected-issue.component'; import { ReceivedIssueComponent } from './record/detail-view/holding-detail-view/serial-holding-detail-view/received-issue/received-issue.component'; import { SerialHoldingDetailViewComponent } from './record/detail-view/holding-detail-view/serial-holding-detail-view/serial-holding-detail-view.component'; -import { HoldingPageDetailComponent } from './record/detail-view/holding-detail-view/holding-page-detail/holding-page-detail.component'; import { IllRequestDetailViewComponent } from './record/detail-view/ill-request-detail-view/ill-request-detail-view.component'; import { ItemDetailViewComponent } from './record/detail-view/item-detail-view/item-detail-view.component'; +import { ItemFeesComponent } from './record/detail-view/item-detail-view/item-fees/item-fees.component'; +import { ItemPageDetailComponent } from './record/detail-view/item-detail-view/item-page-detail/item-page-detail.component'; import { ItemTransactionComponent } from './record/detail-view/item-detail-view/item-transaction/item-transaction.component'; import { ItemTransactionsComponent } from './record/detail-view/item-detail-view/item-transactions/item-transactions.component'; -import { ItemPageDetailComponent } from './record/detail-view/item-detail-view/item-page-detail/item-page-detail.component'; import { ItemTypeDetailViewComponent } from './record/detail-view/item-type-detail-view/item-type-detail-view.component'; import { DayOpeningHoursComponent } from './record/detail-view/library-detail-view/day-opening-hours/day-opening-hours.component'; import { ExceptionDateComponent } from './record/detail-view/library-detail-view/exception-date/exception-date.component'; @@ -212,8 +214,6 @@ import { PreviewEmailModule } from './shared/preview-email/preview-email.module' import { CurrentLibraryPermissionValidator } from './utils/permissions'; import { CustomShortcutHelpComponent } from './widgets/custom-shortcut-help/custom-shortcut-help.component'; import { FrontpageComponent } from './widgets/frontpage/frontpage.component'; -import { LocalPageDetailComponent } from './record/detail-view/entities-detail-view/local/local-page-detail/local-page-detail.component'; -import { RemotePageDetailComponent } from './record/detail-view/entities-detail-view/remote/remote-page-detail/remote-page-detail.component'; /** Init application factory */ export function appInitFactory(appInitializerService: AppInitializerService): () => Promise { @@ -359,7 +359,8 @@ export function appInitFactory(appInitializerService: AppInitializerService): () HoldingPageDetailComponent, ItemPageDetailComponent, LocalPageDetailComponent, - RemotePageDetailComponent + RemotePageDetailComponent, + ItemFeesComponent ], imports: [ AppRoutingModule, diff --git a/projects/admin/src/app/record/brief-view/patron-transaction-events-brief-view/patron-transaction-event-overdue.component.html b/projects/admin/src/app/record/brief-view/patron-transaction-events-brief-view/patron-transaction-event-overdue.component.html index 26fdc67cc..de391529a 100644 --- a/projects/admin/src/app/record/brief-view/patron-transaction-events-brief-view/patron-transaction-event-overdue.component.html +++ b/projects/admin/src/app/record/brief-view/patron-transaction-events-brief-view/patron-transaction-event-overdue.component.html @@ -37,7 +37,11 @@
}
Patron
- {{ parent.patron.pid | patronName | async }} + @if (parent.patron.barcode) { + {{ parent.patron.pid | patronName | async }} + } @else { + {{ parent.patron.pid | patronName | async }} + }
diff --git a/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.html b/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.html index 523036d34..98ef38622 100644 --- a/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.html +++ b/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.html @@ -225,6 +225,11 @@

Issue data

+ @if ((record.metadata | keyExists:'legacy_checkout_count') || (record.metadata | keyExists:'legacy_circulation_rules')) {
diff --git a/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.ts b/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.ts index 0625fcd16..63db511b4 100644 --- a/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.ts +++ b/projects/admin/src/app/record/detail-view/item-detail-view/item-detail-view.component.ts @@ -20,7 +20,7 @@ import { IssueService } from '@app/admin/service/issue.service'; import { RecordPermissionService } from '@app/admin/service/record-permission.service'; import { RecordService } from '@rero/ng-core'; import { DetailRecord } from '@rero/ng-core/lib/record/detail/view/detail-record'; -import { IPermissions, IssueItemStatus, PERMISSIONS, UserService } from '@rero/shared'; +import { IPermissions, IssueItemStatus, PERMISSIONS, PERMISSION_OPERATOR, UserService } from '@rero/shared'; import moment from 'moment'; import { Observable, Subscription } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; @@ -99,11 +99,9 @@ export class ItemDetailViewComponent implements DetailRecord, OnInit, OnDestroy .sort((a: string, b: string) => new Date(b).getTime() - new Date(a).getTime()); } - /** - * Permissions - * @return Object with all permissions - */ + /** Permissions */ permissions: IPermissions = PERMISSIONS; + permissionOperator = PERMISSION_OPERATOR; /** * Constructor diff --git a/projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.html b/projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.html new file mode 100644 index 000000000..9ddd444c6 --- /dev/null +++ b/projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.html @@ -0,0 +1,45 @@ + +@if (fees.length > 0) { +
+
+ Fees +
+ {{ 'Total' | translate }} + {{ total | currency: organisation.default_currency }} +
+
+
+
+
Patron
+
Amount
+
+ @for (fee of fees; track fee) { + @if (fee.metadata.patron.pid | getRecord:'patrons' | async; as patron) { + + } + } +
+
+} diff --git a/projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.ts b/projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.ts new file mode 100644 index 000000000..a48ce3599 --- /dev/null +++ b/projects/admin/src/app/record/detail-view/item-detail-view/item-fees/item-fees.component.ts @@ -0,0 +1,61 @@ +/* + * RERO ILS UI + * Copyright (C) 2019-2024 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 + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +import { Component, Input, OnInit } from '@angular/core'; +import { PatronTransactionApiService } from '@app/admin/api/patron-transaction-api.service'; +import { OrganisationService } from '@app/admin/service/organisation.service'; +import { tap } from 'rxjs'; + +@Component({ + selector: 'admin-item-fees', + templateUrl: './item-fees.component.html' +}) +export class ItemFeesComponent implements OnInit { + + /** Item pid */ + @Input() itemPid: string; + + /** Fees */ + fees: any[] = []; + + /** Total fees */ + total: number = 0; + + /** + * Get the current organisation + * @return Organisation + */ + get organisation() { + return this.organisationService.organisation; + } + + /** + * Constructor + * @param patronTransactionApiService - PatronTransactionApiService + * @param organisationService - OrganisationService + */ + public constructor( + private patronTransactionApiService: PatronTransactionApiService, + private organisationService: OrganisationService + ) {} + + /** OnInit hook */ + ngOnInit(): void { + this.patronTransactionApiService.getActiveFeesByItemPid(this.itemPid) + .pipe(tap((fees: any) => fees.map((fee: any) => this.total += fee.metadata.total_amount))) + .subscribe((fees: any) => this.fees = fees); + } +}