2 * Common code for mananging holds
4 import {Injectable} from '@angular/core';
5 import {Observable} from 'rxjs';
6 import {map, mergeMap} from 'rxjs/operators';
7 import {IdlObject} from '@eg/core/idl.service';
8 import {NetService} from '@eg/core/net.service';
9 import {PcrudService} from '@eg/core/pcrud.service';
10 import {EventService, EgEvent} from '@eg/core/event.service';
11 import {AuthService} from '@eg/core/auth.service';
12 import {BibRecordService,
13 BibRecordSummary} from '@eg/share/catalog/bib-record.service';
15 // Response from a place-holds API call.
16 export interface HoldRequestResult {
22 // Values passed to the place-holds API call.
23 export interface HoldRequest {
30 notifyEmail?: boolean;
34 thawDate?: string; // ISO date
36 holdableFormats?: {[target: number]: string};
37 result?: HoldRequestResult;
40 // A fleshed hold request target object containing whatever data is
41 // available for each hold type / target. E.g. a TITLE hold will
42 // not have a value for 'callNum', but a COPY hold will, since all
43 // copies have call numbers. Every HoldRequestTarget will have a bibId and
44 // bibSummary. Some values come directly from the API call, others
46 export interface HoldRequestTarget {
48 metarecord?: IdlObject;
49 bibrecord?: IdlObject;
51 bibSummary?: BibRecordSummary;
57 metarecord_filters?: any;
60 /** Service for performing various hold-related actions */
63 export class HoldsService {
66 private evt: EventService,
67 private net: NetService,
68 private auth: AuthService,
69 private bib: BibRecordService,
72 placeHold(request: HoldRequest): Observable<HoldRequest> {
74 let method = 'open-ils.circ.holds.test_and_create.batch';
75 if (request.override) { method = method + '.override'; }
77 return this.net.request(
78 'open-ils.circ', method, this.auth.token(), {
79 patronid: request.recipient,
80 pickup_lib: request.pickupLib,
81 hold_type: request.holdType,
82 email_notify: request.notifyEmail,
83 phone_notify: request.notifyPhone,
84 thaw_date: request.thawDate,
85 frozen: request.frozen,
86 sms_notify: request.notifySms,
87 sms_carrier: request.smsCarrier,
88 holdable_formats_map: request.holdableFormats
93 let result = resp.result;
94 const holdResult: HoldRequestResult = {success: true};
96 // API can return an ID, an array of events, or a hash
99 if (Number(result) > 0) {
100 // On success, the API returns the hold ID.
101 holdResult.holdId = result;
102 console.debug(`Hold successfully placed ${result}`);
105 holdResult.success = false;
106 console.info('Hold request failed: ', result);
108 if (Array.isArray(result)) { result = result[0]; }
110 if (this.evt.parse(result)) {
111 holdResult.evt = this.evt.parse(result);
113 holdResult.evt = this.evt.parse(result.last_event);
117 request.result = holdResult;
123 getHoldTargetMeta(holdType: string, holdTarget: number | number[],
124 orgId?: number): Observable<HoldRequestTarget> {
126 const targetIds = [].concat(holdTarget);
128 return this.net.request(
130 'open-ils.circ.hold.get_metadata',
131 holdType, targetIds, orgId
132 ).pipe(mergeMap(meta => {
133 const target: HoldRequestTarget = meta;
134 target.bibId = target.bibrecord.id();
135 target.callNum = meta.volume; // map to client terminology
137 return this.bib.getBibSummary(target.bibId)
139 target.bibSummary = sum;
146 * Update a list of holds.
147 * Returns observable of results, one per hold.
148 * Result is either a Number (hold ID) or an EgEvent object.
150 updateHolds(holds: IdlObject[]): Observable<any> {
152 return this.net.request(
154 'open-ils.circ.hold.update.batch',
155 this.auth.token(), holds
156 ).pipe(map(response => {
158 if (Number(response) > 0) { return Number(response); }
160 if (Array.isArray(response)) { response = response[0]; }
162 const evt = this.evt.parse(response);
164 console.warn('Hold update returned event', evt);