From 52a3dd19b4115f800fd862177ec855a471e6a827 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Thu, 8 Jul 2021 10:19:43 -0400 Subject: [PATCH] LP1933275 Staff catalog holdings view shows correct counts teaches the Holdings view to determine the number of copies and call numbers attached to each org unit based on the full data set (via new API) instead of copies in hand, since we may only have copies in hand for a subset of child org units. Signed-off-by: Bill Erickson Signed-off-by: Mary Llewellyn Signed-off-by: Jane Sandberg --- .../app/staff/catalog/record/holdings.component.ts | 56 +++++++++-------- .../lib/OpenILS/Application/Search/Biblio.pm | 72 ++++++++++++++++++++++ 2 files changed, 104 insertions(+), 24 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts index c3388477d5..43fd1a0c8c 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts @@ -2,7 +2,7 @@ import {Component, OnInit, Input, ViewChild, ViewEncapsulation } from '@angular/core'; import {Router} from '@angular/router'; import {Observable, Observer, of, empty} from 'rxjs'; -import {map} from 'rxjs/operators'; +import {map, tap, concatMap} from 'rxjs/operators'; import {Pager} from '@eg/share/util/pager'; import {IdlObject, IdlService} from '@eg/core/idl.service'; import {StaffCatalogService} from '../catalog.service'; @@ -150,6 +150,8 @@ export class HoldingsMaintenanceComponent implements OnInit { orgClassCallback: (orgId: number) => string; marked_orgs: number[] = []; + copyCounts: {[orgId: number]: {}} = {}; + private _recId: number; @Input() set recordId(id: number) { this._recId = id; @@ -405,8 +407,8 @@ export class HoldingsMaintenanceComponent implements OnInit { setTreeCounts(node: HoldingsTreeNode) { if (node.nodeType === 'org') { - node.copyCount = 0; - node.callNumCount = 0; + node.copyCount = this.copyCounts[node.target.id() + ''].copies; + node.callNumCount = this.copyCounts[node.target.id() + ''].call_numbers; } else if (node.nodeType === 'callNum') { node.copyCount = 0; } @@ -416,13 +418,9 @@ export class HoldingsMaintenanceComponent implements OnInit { node.children.forEach(child => { this.setTreeCounts(child); if (node.nodeType === 'org') { - node.copyCount += child.copyCount; - if (child.nodeType === 'callNum') { - node.callNumCount++; - } else { + if (child.nodeType !== 'callNum') { hasChildOrgWithData = child.callNumCount > 0; hasChildOrgSansData = child.callNumCount === 0; - node.callNumCount += child.callNumCount; } } else if (node.nodeType === 'callNum') { node.copyCount = node.children.length; @@ -526,21 +524,31 @@ export class HoldingsMaintenanceComponent implements OnInit { this.itemCircsNeeded = []; - this.pcrud.search('acn', - { record: this.recordId, - owning_lib: this.org.fullPath(this.contextOrg, true), - deleted: 'f', - label: {'!=' : '##URI##'} - }, { - flesh: 3, - flesh_fields: { - acp: ['status', 'location', 'circ_lib', 'parts', 'notes', - 'tags', 'age_protect', 'copy_alerts', 'latest_inventory'], - acn: ['prefix', 'suffix', 'copies'], - acli: ['inventory_workstation'] - } - }, - {authoritative: true} + return this.net.request( + 'open-ils.search', + 'open-ils.search.biblio.record.copy_counts.global.staff', + this.recordId + ).pipe( + tap(counts => this.copyCounts = counts), + concatMap(_ => { + + return this.pcrud.search('acn', + { record: this.recordId, + owning_lib: this.org.fullPath(this.contextOrg, true), + deleted: 'f', + label: {'!=' : '##URI##'} + }, { + flesh: 3, + flesh_fields: { + acp: ['status', 'location', 'circ_lib', 'parts', 'notes', + 'tags', 'age_protect', 'copy_alerts', 'latest_inventory'], + acn: ['prefix', 'suffix', 'copies'], + acli: ['inventory_workstation'] + } + }, + {authoritative: true} + ); + }) ).subscribe( callNum => this.appendCallNum(callNum), err => {}, @@ -550,7 +558,7 @@ export class HoldingsMaintenanceComponent implements OnInit { ok => this.flattenHoldingsTree(observer) ); } - ); + ); }); } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm index ab372c872e..e780d085e6 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm @@ -3290,6 +3290,78 @@ sub get_one_record_summary { }; } +__PACKAGE__->register_method( + method => 'record_copy_counts_global', + api_name => 'open-ils.search.biblio.record.copy_counts.global.staff', + signature => { + desc => q/Returns a count of copies and call numbers for each org + unit, including items attached to each org unit plus + a sum of counts for all descendants./, + params => [ + {desc => 'Record ID', type => 'number'} + ], + return => { + desc => 'Hash of org unit ID => {copy: $count, call_number: $id}' + } + } +); + +sub record_copy_counts_global { + my ($self, $client, $rec_id) = @_; + + my $copies = new_editor()->json_query({ + select => { + acp => [{column => 'id', alias => 'copy_id'}, 'circ_lib'], + acn => [{column => 'id', alias => 'cn_id'}, 'owning_lib'] + }, + from => {acn => {acp => {type => 'left'}}}, + where => { + '+acp' => { + '-or' => [ + {deleted => 'f'}, + {id => undef} # left join + ] + }, + '+acn' => {deleted => 'f', record => $rec_id} + } + }); + + my $hash = {}; + my %seen_cn; + + for my $copy (@$copies) { + my $org = $copy->{circ_lib} || $copy->{owning_lib}; + $hash->{$org} = {copies => 0, call_numbers => 0} unless $hash->{$org}; + $hash->{$org}->{copies}++ if $copy->{circ_lib}; + + if (!$seen_cn{$copy->{cn_id}}) { + $seen_cn{$copy->{cn_id}} = 1; + $hash->{$org}->{call_numbers}++; + } + } + + my $sum; + $sum = sub { + my $node = shift; + my $h = $hash->{$node->id} || {copies => 0, call_numbers => 0}; + delete $h->{cn_id}; + + for my $child (@{$node->children}) { + my $vals = $sum->($child); + $h->{copies} += $vals->{copies}; + $h->{call_numbers} += $vals->{call_numbers}; + } + + $hash->{$node->id} = $h; + + return $h; + }; + + $sum->($U->get_org_tree); + + return $hash; +} + 1; -- 2.11.0