LP1913807 Staff catalog shows preferred lib holdings counts
[evergreen-equinox.git] / Open-ILS / src / eg2 / src / app / share / catalog / bib-record.service.ts
1 import {Injectable} from '@angular/core';
2 import {Observable, from} from 'rxjs';
3 import {mergeMap, map, tap} from 'rxjs/operators';
4 import {OrgService} from '@eg/core/org.service';
5 import {UnapiService} from '@eg/share/catalog/unapi.service';
6 import {IdlService, IdlObject} from '@eg/core/idl.service';
7 import {NetService} from '@eg/core/net.service';
8 import {PcrudService} from '@eg/core/pcrud.service';
9
10 export const NAMESPACE_MAPS = {
11     'mods':     'http://www.loc.gov/mods/v3',
12     'biblio':   'http://open-ils.org/spec/biblio/v1',
13     'holdings': 'http://open-ils.org/spec/holdings/v1',
14     'indexing': 'http://open-ils.org/spec/indexing/v1'
15 };
16
17 export const HOLDINGS_XPATH =
18     '/holdings:holdings/holdings:counts/holdings:count';
19
20 interface EResourceUrl {
21     href: string;
22     note: string;
23     label: string;
24 }
25
26 export interface HoldingsSummary {
27     org_unit: number;
28     depth: number;
29     unshadow: number;
30     count: number;
31     available: number;
32     transcendant: number;
33 }
34
35 export class BibRecordSummary {
36     id: number; // == record.id() for convenience
37     metabibId: number; // If present, this is a metabib summary
38     metabibRecords: number[]; // all constituent bib records
39     orgId: number;
40     orgDepth: number;
41     record: IdlObject;
42     display: any;
43     attributes: any;
44     holdingsSummary: HoldingsSummary[];
45     prefOuHoldingsSummary: HoldingsSummary[];
46     holdCount: number;
47     bibCallNumber: string;
48     firstCallNumber: string;
49     net: NetService;
50     displayHighlights: {[name: string]: string | string[]} = {};
51     eResourceUrls: EResourceUrl[] = [];
52     copies: any[];
53
54     constructor(record: IdlObject, orgId: number, orgDepth?: number) {
55         this.id = Number(record.id());
56         this.record = record;
57         this.orgId = orgId;
58         this.orgDepth = orgDepth;
59         this.display = {};
60         this.attributes = {};
61         this.bibCallNumber = null;
62         this.metabibRecords = [];
63     }
64
65     // Get -> Set -> Return bib-level call number
66     getBibCallNumber(): Promise<string> {
67
68         if (this.bibCallNumber !== null) {
69             return Promise.resolve(this.bibCallNumber);
70         }
71
72         return this.net.request(
73             'open-ils.cat',
74             'open-ils.cat.biblio.record.marc_cn.retrieve',
75             this.id, null, this.orgId
76         ).toPromise().then(cnArray => {
77             if (cnArray && cnArray.length > 0) {
78                 const key1 = Object.keys(cnArray[0])[0];
79                 this.bibCallNumber = cnArray[0][key1];
80             } else {
81                 this.bibCallNumber = '';
82             }
83             return this.bibCallNumber;
84         });
85     }
86 }
87
88 @Injectable()
89 export class BibRecordService {
90
91     // Cache of bib editor / creator objects
92     // Assumption is this list will be limited in size.
93     userCache: {[id: number]: IdlObject};
94
95     constructor(
96         private idl: IdlService,
97         private net: NetService,
98         private org: OrgService,
99         private unapi: UnapiService,
100         private pcrud: PcrudService
101     ) {
102         this.userCache = {};
103     }
104
105     getBibSummary(id: number,
106         orgId?: number, isStaff?: boolean): Observable<BibRecordSummary> {
107         return this.getBibSummaries([id], orgId, isStaff);
108     }
109
110     getBibSummaries(bibIds: number[], orgId?: number,
111         isStaff?: boolean, options?: any): Observable<BibRecordSummary> {
112
113         if (bibIds.length === 0) { return from([]); }
114         if (!orgId) { orgId = this.org.root().id(); }
115
116         let method = 'open-ils.search.biblio.record.catalog_summary';
117         if (isStaff) { method += '.staff'; }
118
119         return this.net.request('open-ils.search', method, orgId, bibIds, options)
120         .pipe(map(bibSummary => {
121             const summary = new BibRecordSummary(bibSummary.record, orgId);
122             summary.net = this.net; // inject
123             summary.display = bibSummary.display;
124             summary.attributes = bibSummary.attributes;
125             summary.holdCount = bibSummary.hold_count;
126             summary.holdingsSummary = bibSummary.copy_counts;
127             summary.eResourceUrls = bibSummary.urls;
128             summary.copies = bibSummary.copies;
129             summary.firstCallNumber = bibSummary.first_call_number;
130             summary.prefOuHoldingsSummary = bibSummary.pref_ou_copy_counts;
131
132             return summary;
133         }));
134     }
135
136     getMetabibSummaries(metabibIds: number[],
137         orgId?: number, isStaff?: boolean, options?: any): Observable<BibRecordSummary> {
138
139         if (metabibIds.length === 0) { return from([]); }
140         if (!orgId) { orgId = this.org.root().id(); }
141
142         let method = 'open-ils.search.biblio.metabib.catalog_summary';
143         if (isStaff) { method += '.staff'; }
144
145         return this.net.request('open-ils.search', method, orgId, metabibIds, options)
146         .pipe(map(metabibSummary => {
147             const summary = new BibRecordSummary(metabibSummary.record, orgId);
148             summary.net = this.net; // inject
149             summary.metabibId = Number(metabibSummary.metabib_id);
150             summary.metabibRecords = metabibSummary.metabib_records;
151             summary.display = metabibSummary.display;
152             summary.attributes = metabibSummary.attributes;
153             summary.holdCount = metabibSummary.hold_count;
154             summary.holdingsSummary = metabibSummary.copy_counts;
155             summary.copies = metabibSummary.copies;
156             summary.firstCallNumber = metabibSummary.first_call_number;
157             summary.prefOuHoldingsSummary = metabibSummary.pref_ou_copy_counts;
158
159             return summary;
160         }));
161     }
162 }
163
164