]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/share/holds/holds.service.ts
a6ddb7e881b5ecf6a6b073c4b769783f0cbacb90
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / share / holds / holds.service.ts
1 /**
2  * Common code for mananging holds
3  */
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';
14
15 // Response from a place-holds API call.
16 export interface HoldRequestResult {
17     success: boolean;
18     holdId?: number;
19     evt?: EgEvent;
20 }
21
22 // Values passed to the place-holds API call.
23 export interface HoldRequest {
24     holdType: string;
25     holdTarget: number;
26     recipient: number;
27     requestor: number;
28     pickupLib: number;
29     override?: boolean;
30     notifyEmail?: boolean;
31     notifyPhone?: string;
32     notifySms?: string;
33     smsCarrier?: string;
34     thawDate?: string; // ISO date
35     frozen?: boolean;
36     holdableFormats?: {[target: number]: string};
37     result?: HoldRequestResult;
38 }
39
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
45 // applied locally.
46 export interface HoldRequestTarget {
47     target: number;
48     metarecord?: IdlObject;
49     bibrecord?: IdlObject;
50     bibId?: number;
51     bibSummary?: BibRecordSummary;
52     part?: IdlObject;
53     callNum?: IdlObject;
54     copy?: IdlObject;
55     issuance?: IdlObject;
56     metarecord_filters?: any;
57 }
58
59 /** Service for performing various hold-related actions */
60
61 @Injectable()
62 export class HoldsService {
63
64     constructor(
65         private evt: EventService,
66         private net: NetService,
67         private auth: AuthService,
68         private bib: BibRecordService,
69     ) {}
70
71     placeHold(request: HoldRequest): Observable<HoldRequest> {
72
73         let method = 'open-ils.circ.holds.test_and_create.batch';
74         if (request.override) { method = method + '.override'; }
75
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
88             },
89             [request.holdTarget]
90         ).pipe(map(
91             resp => {
92                 let result = resp.result;
93                 const holdResult: HoldRequestResult = {success: true};
94
95                 // API can return an ID, an array of events, or a hash
96                 // of info.
97
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}`);
102
103                 } else {
104                     holdResult.success = false;
105                     console.info('Hold request failed: ', result);
106
107                     if (Array.isArray(result)) { result = result[0]; }
108
109                     if (this.evt.parse(result)) {
110                         holdResult.evt = this.evt.parse(result);
111                     } else {
112                         holdResult.evt = this.evt.parse(result.last_event);
113                     }
114                 }
115
116                 request.result = holdResult;
117                 return request;
118             }
119         ));
120     }
121
122     getHoldTargetMeta(holdType: string, holdTarget: number | number[],
123         orgId?: number): Observable<HoldRequestTarget> {
124
125         const targetIds = [].concat(holdTarget);
126
127         return this.net.request(
128             'open-ils.circ',
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
135
136             return this.bib.getBibSummary(target.bibId)
137             .pipe(map(sum => {
138                 target.bibSummary = sum;
139                 return target;
140             }));
141         }));
142     }
143
144     /**
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.
148       */
149     updateHolds(holds: IdlObject[]): Observable<any> {
150
151         return this.net.request(
152             'open-ils.circ',
153             'open-ils.circ.hold.update.batch',
154             this.auth.token(), holds
155         ).pipe(map(response => {
156
157             if (Number(response) > 0) { return Number(response); }
158
159             if (Array.isArray(response)) { response = response[0]; }
160
161             const evt = this.evt.parse(response);
162
163             console.warn('Hold update returned event', evt);
164             return evt;
165         }));
166     }
167 }
168
169
170