1 import {Component, OnInit, Input, ViewChild, Renderer2} from '@angular/core';
2 import {Observable} from 'rxjs';
3 import {switchMap, map, tap} from 'rxjs/operators';
4 import {IdlObject} from '@eg/core/idl.service';
5 import {NetService} from '@eg/core/net.service';
6 import {AuthService} from '@eg/core/auth.service';
7 import {EventService} from '@eg/core/event.service';
8 import {ToastService} from '@eg/share/toast/toast.service';
9 import {AlertDialogComponent} from '@eg/share/dialog/alert.component';
10 import {StringComponent} from '@eg/share/string/string.component';
11 import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
13 /* Transfer holdings (AKA asset.call_number) to a target bib record. */
16 selector: 'eg-transfer-holdings',
17 templateUrl: 'transfer-holdings.component.html'
20 export class TransferHoldingsComponent implements OnInit {
22 // Array of 'acn' objects.
23 // Assumes all acn's are children of the same bib record.
24 @Input() callNums: IdlObject[];
27 // All call numbers will be transferred to this record ID.
28 @Input() targetRecId: number;
30 // Optional. If set, all call numbers will transfer to this org
31 // unit (owning lib) in addition to transfering to the select bib
33 @Input() targetOrgId: number;
35 @ViewChild('successMsg', {static: false})
36 private successMsg: StringComponent;
38 @ViewChild('noTargetMsg', {static: false})
39 private noTargetMsg: StringComponent;
41 @ViewChild('alertDialog', {static: false})
42 private alertDialog: AlertDialogComponent;
44 @ViewChild('progressDialog', {static: false})
45 private progressDialog: ProgressDialogComponent;
50 private toast: ToastService,
51 private net: NetService,
52 private auth: AuthService,
53 private evt: EventService) {}
57 // Resolves with true if transfer completed, false otherwise.
58 // Assumes all volumes are transferred to the same bib record.
59 transferHoldings(): Promise<Boolean> {
60 if (!this.callNums || this.callNums.length === 0) {
61 return Promise.resolve(false);
64 if (!this.targetRecId) {
65 this.toast.warning(this.noTargetMsg.text);
66 return Promise.resolve(false);
71 // Group the transfers by owning library.
72 const transferVols: {[orgId: number]: number[]} = {};
74 if (this.targetOrgId) {
76 // Transfering all call numbers to the same bib record
77 // and owning library.
78 transferVols[+this.targetOrgId] = this.callNums.map(cn => cn.id());
82 // Transfering all call numbers to the same bib record
83 // while retaining existing owning library.
84 this.callNums.forEach(cn => {
85 const orgId = Number(cn.owning_lib());
86 if (!transferVols[orgId]) { transferVols[orgId] = []; }
87 transferVols[orgId].push(cn.id());
91 this.progressDialog.update({
93 max: Object.keys(transferVols).length
95 this.progressDialog.open();
97 return this.performTransfers(transferVols)
99 this.progressDialog.close();
104 performTransfers(transferVols: any): Promise<Boolean> {
105 const orgId = Object.keys(transferVols)[0];
106 const volIds = transferVols[orgId];
108 // Avoid re-processing
109 delete transferVols[orgId];
111 // Note the AngJS client also assumes .override.
112 const method = 'open-ils.cat.asset.volume.batch.transfer.override';
114 return this.net.request('open-ils.cat', method, this.auth.token(), {
115 docid: this.targetRecId,
118 }).toPromise().then(resp => {
119 const evt = this.evt.parse(resp);
121 if (evt || Number(resp) !== 1) {
123 this.eventDesc = evt ? evt.desc : '';
125 // Failure -- stop short there to avoid alert storm.
126 return this.alertDialog.open().toPromise()
127 .then(_ => { this.eventDesc = ''; return false; });
130 this.progressDialog.increment();
132 if (Object.keys(transferVols).length > 0) {
133 return this.performTransfers(transferVols);
136 return true; // All done