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;
56 metarecord_filters?: any;
59 /** Service for performing various hold-related actions */
62 export class HoldsService {
65 private evt: EventService,
66 private net: NetService,
67 private auth: AuthService,
68 private bib: BibRecordService,
71 placeHold(request: HoldRequest): Observable<HoldRequest> {
73 let method = 'open-ils.circ.holds.test_and_create.batch';
74 if (request.override) { method = method + '.override'; }
76 return this.net.request(
77 'open-ils.circ', method, this.auth.token(), {
78 patronid: request.recipient,
79 pickup_lib: request.pickupLib,
80 hold_type: request.holdType,
81 email_notify: request.notifyEmail,
82 phone_notify: request.notifyPhone,
83 thaw_date: request.thawDate,
84 frozen: request.frozen,
85 sms_notify: request.notifySms,
86 sms_carrier: request.smsCarrier,
87 holdable_formats_map: request.holdableFormats
92 let result = resp.result;
93 const holdResult: HoldRequestResult = {success: true};
95 // API can return an ID, an array of events, or a hash
98 if (Number(result) > 0) {
99 // On success, the API returns the hold ID.
100 holdResult.holdId = result;
101 console.debug(`Hold successfully placed ${result}`);
104 holdResult.success = false;
105 console.info('Hold request failed: ', result);
107 if (Array.isArray(result)) { result = result[0]; }
109 if (this.evt.parse(result)) {
110 holdResult.evt = this.evt.parse(result);
112 holdResult.evt = this.evt.parse(result.last_event);
116 request.result = holdResult;
122 getHoldTargetMeta(holdType: string, holdTarget: number | number[],
123 orgId?: number): Observable<HoldRequestTarget> {
125 const targetIds = [].concat(holdTarget);
127 return this.net.request(
129 'open-ils.circ.hold.get_metadata',
130 holdType, targetIds, orgId
131 ).pipe(mergeMap(meta => {
132 const target: HoldRequestTarget = meta;
133 target.bibId = target.bibrecord.id();
134 target.callNum = meta.volume; // map to client terminology
136 return this.bib.getBibSummary(target.bibId)
138 target.bibSummary = sum;
145 * Update a list of holds.
146 * Returns observable of results, one per hold.
147 * Result is either a Number (hold ID) or an EgEvent object.
149 updateHolds(holds: IdlObject[]): Observable<any> {
151 return this.net.request(
153 'open-ils.circ.hold.update.batch',
154 this.auth.token(), holds
155 ).pipe(map(response => {
157 if (Number(response) > 0) { return Number(response); }
159 if (Array.isArray(response)) { response = response[0]; }
161 const evt = this.evt.parse(response);
163 console.warn('Hold update returned event', evt);