place holds continued
authorBill Erickson <berickxx@gmail.com>
Tue, 20 Nov 2018 16:04:37 +0000 (11:04 -0500)
committerBill Erickson <berickxx@gmail.com>
Fri, 30 Nov 2018 16:34:20 +0000 (11:34 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/core/perm.service.ts
Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.html
Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.ts
Open-ILS/src/eg2/src/app/staff/share/hold.service.ts

index 44d3c63..2b3a471 100644 (file)
@@ -41,7 +41,8 @@ export class PermService {
     }
 
     // workstation required
-    hasWorkPermHere(permNames: string[]): Promise<HasPermHereResult> {
+    hasWorkPermHere(permNames: string | string[]): Promise<HasPermHereResult> {
+        permNames = [].concat(permNames);
         const wsId: number = +this.auth.user().wsid();
 
         if (!wsId) {
index b7857e5..a161e22 100644 (file)
 <div class="row"><div class="col-lg-12"><hr/></div></div>
 
 <div class="row font-weight-bold pt-3 ml-1 mr-1">
-  <div class="col-lg-12" i18n>Placing hold(s) on record(s)</div>
+  <div class="col-lg-12" i18n>Placing 
+    <ng-container *ngIf="holdType == 'M'">METARECORD</ng-container> 
+    <ng-container *ngIf="holdType == 'T'">TITLE</ng-container> 
+    <ng-container *ngIf="holdType == 'V'">VOLUME</ng-container> 
+    <ng-container *ngIf="holdType == 'F'">FORCE COPY</ng-container> 
+    <ng-container *ngIf="holdType == 'C'">COPY</ng-container> 
+    <ng-container *ngIf="holdType == 'R'">RECALL</ng-container> 
+    <ng-container *ngIf="holdType == 'I'">ISSUANCE</ng-container> 
+    <ng-container *ngIf="holdType == 'P'">PARTS</ng-container> 
+    hold on record(s)</div>
 </div>
 
 <div class="hold-records-list common-form striped-even">
     <div class="col-lg-1" i18n>TCN</div>
     <div class="col-lg-2" i18n>Call Number</div>
     <div class="col-lg-1" i18n>Barcode</div>
-    <div class="col-lg-3" i18n>Holds Status</div>
+    <div class="col-lg-2" i18n>Holds Status</div>
+    <div class="col-lg-1" i18n>Override</div>
   </div>
   <div class="row mt-1 ml-1 mr-1" *ngFor="let ctx of holdContexts">
     <ng-container *ngIf="ctx.bibSummary">
           <span class="font-italic">ANY</span>
         </ng-container>
       </div>
-      <div class="col-lg-3">
+      <div class="col-lg-2">
         <ng-container *ngIf="!ctx.lastRequest">
           <div class="alert alert-info" i18n>Hold Pending</div>
         </ng-container>
             <div class="alert alert-success" i18n>Hold Succeeded</div>
           </ng-container>
           <ng-container *ngIf="!ctx.lastRequest.result.success">
-            <div class="alert alert-error">
-              {{ctx.lastRequest.result.last_event.toString()}}
+            <div class="alert alert-danger">
+              {{ctx.lastRequest.result.evt.textcode}}
             </div>
           </ng-container>
         </ng-container>
       </div>
+      <div class="col-lg-1">
+        <ng-container *ngIf="canOverride(ctx)">
+          <button class="btn btn-info" (click)="override(ctx)">Override</button>
+        </ng-container>
+      </div>
     </ng-container>
   </div>
 </div>
index ab77e31..e813a94 100644 (file)
@@ -4,6 +4,7 @@ import {EventService} from '@eg/core/event.service';
 import {NetService} from '@eg/core/net.service';
 import {AuthService} from '@eg/core/auth.service';
 import {PcrudService} from '@eg/core/pcrud.service';
+import {PermService} from '@eg/core/perm.service';
 import {IdlObject} from '@eg/core/idl.service';
 import {BibRecordService, BibRecordSummary} from '@eg/share/catalog/bib-record.service';
 import {CatalogSearchContext, CatalogSearchState} from '@eg/share/catalog/search-context';
@@ -16,6 +17,7 @@ class HoldContext {
     bibSummary: BibRecordSummary;
     holdTarget: number;
     lastRequest: HoldRequest;
+    canOverride?: boolean;
 }
 
 @Component({
@@ -54,7 +56,8 @@ export class HoldComponent implements OnInit {
         private bib: BibRecordService,
         private cat: CatalogService,
         private staffCat: StaffCatalogService,
-        private holds: HoldService
+        private holds: HoldService,
+        private perm: PermService
     ) {
         this.holdContexts = [];
     }
@@ -219,25 +222,53 @@ export class HoldComponent implements OnInit {
         }
     }
 
+    // Attempt hold placement on all targets
     placeHolds(idx?: number) {
         if (!idx) { idx = 0; }
         if (!this.holdTargets[idx]) { return; }
+        this.placeOneHold(this.holdTargets[idx])
+            .then(() => this.placeHolds(idx + 1));
+    }
+
+    placeOneHold(target: number, override?: boolean): Promise<any> {
 
-        this.holds.placeHold({
-            holdTarget: this.holdTargets[idx],
+        return this.holds.placeHold({
+            holdTarget: target,
             holdType: this.holdType,
             recipient: this.user.id(),
             requestor: this.requestor.id(),
-            pickupLib: this.pickupLib
+            pickupLib: this.pickupLib,
+            override: override
 
-        }).subscribe(request => {
+        }).toPromise().then(request => {
             console.log('hold returned: ', request);
+
             const ctx = this.holdContexts.filter(
                 ctx => ctx.holdTarget === request.holdTarget)[0];
             ctx.lastRequest = request;
-            this.placeHolds(idx + 1);
+
+            // If this request failed and was not already an override,
+            // see of this user has permission to override.
+            if (!request.override && 
+                !request.result.success && request.result.evt) {
+
+                const txtcode = request.result.evt.textcode;
+                const perm = txtcode + '.override';
+
+                return this.perm.hasWorkPermHere(perm).then(
+                    permResult => ctx.canOverride = permResult[perm]);
+            }
         });
     }
+
+    override(ctx: HoldContext) {
+        this.placeOneHold(ctx.holdTarget, true);
+    }
+
+    canOverride(ctx: HoldContext): boolean {
+        return ctx.lastRequest && 
+                !ctx.lastRequest.result.success && ctx.canOverride;
+    }
 }
 
 
index dcd9cbb..7004a46 100644 (file)
@@ -8,6 +8,12 @@ import {NetService} from '@eg/core/net.service';
 import {EventService, EgEvent} from '@eg/core/event.service';
 import {AuthService} from '@eg/core/auth.service';
 
+export interface HoldRequestResult {
+    success: boolean;
+    holdId?: number;
+    evt?: EgEvent;
+};
+
 export interface HoldRequest {
     holdType: string;
     holdTarget: number;
@@ -16,9 +22,7 @@ export interface HoldRequest {
     pickupLib: number;
     override?: boolean;
     //holdableFormats?: {[id: number]: string[]};
-
-    // result contains 'success', and (parsed) 'last_event'
-    result?: any;
+    result?: HoldRequestResult
     // ...
 };
 
@@ -32,11 +36,12 @@ export class HoldService {
     ) {}
 
     placeHold(request: HoldRequest): Observable<HoldRequest> {
+        
+        let method = 'open-ils.circ.holds.test_and_create.batch';
+        if (request.override) { method = method + '.override'; }
 
         return this.net.request(
-            'open-ils.circ',
-            'open-ils.circ.holds.test_and_create.batch', 
-            this.auth.token(), {
+            'open-ils.circ', method, this.auth.token(), {
                 patronid: request.recipient,
                 pickup_lib: request.pickupLib,
                 hold_type: request.holdType,
@@ -45,15 +50,31 @@ export class HoldService {
             [request.holdTarget]
         ).pipe(map(
             resp => {
-                const result = resp.result;
-                result.last_event = this.evt.parse(result.last_event);
-                result.success = Boolean(Number(result.success));
-                if (result.sucesss) {
-                    console.debug('Hold successfully placed');
-                } else if (result.last_event) {
-                    console.warn(`Hold Request returned: ${result.last_event}`);
+                let result = resp.result;
+                const holdResult: HoldRequestResult = {success: true};
+
+                // API can return an ID, an array of events, or a hash
+                // of info.
+
+                if (Number(result) > 0) {
+                    // On success, the API returns the hold ID.
+                    holdResult.holdId = result;
+                    console.debug(`Hold successfully placed ${result}`);
+
+                } else {
+                    holdResult.success = false;
+                    console.info('Hold request failed: ', result);
+
+                    if (Array.isArray(result)) { result = result[0]; }
+
+                    if (this.evt.parse(result)) {
+                        holdResult.evt = this.evt.parse(result);
+                    } else {
+                        holdResult.evt = this.evt.parse(result.last_event);
+                    }
                 }
-                request.result = result;
+
+                request.result = holdResult;
                 return request;
             }
         ));