LP1904036 Renew; Batch Checkout/Renew; shared circ components
authorBill Erickson <berickxx@gmail.com>
Fri, 26 Feb 2021 22:04:40 +0000 (17:04 -0500)
committerGalen Charlton <gmc@equinoxOLI.org>
Fri, 28 Oct 2022 00:13:24 +0000 (20:13 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Jane Sandberg <js7389@princeton.edu>
Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
Open-ILS/src/eg2/src/app/staff/circ/patron/checkout.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/checkout.component.ts
Open-ILS/src/eg2/src/app/staff/circ/patron/patron.component.html
Open-ILS/src/eg2/src/app/staff/share/circ/circ.module.ts
Open-ILS/src/eg2/src/app/staff/share/circ/circ.service.ts
Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.html
Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.ts

index b1e12fe..ab5b137 100644 (file)
@@ -1,9 +1,6 @@
 
 <eg-progress-dialog #progressDialog></eg-progress-dialog>
 <eg-barcode-select #barcodeSelect></eg-barcode-select>
-
-<eg-precat-checkout-dialog #precatDialog [barcode]="checkoutBarcode">
-</eg-precat-checkout-dialog>
 <eg-copy-alerts-dialog #copyAlertsDialog></eg-copy-alerts-dialog>
 
 <eg-prompt-dialog #nonCatCount
index 62aacad..9a7abde 100644 (file)
@@ -16,7 +16,6 @@ import {GridComponent} from '@eg/share/grid/grid.component';
 import {Pager} from '@eg/share/util/pager';
 import {StoreService} from '@eg/core/store.service';
 import {ServerStoreService} from '@eg/core/server-store.service';
-import {PrecatCheckoutDialogComponent} from '@eg/staff/share/circ/precat-dialog.component';
 import {AudioService} from '@eg/share/util/audio.service';
 import {CopyAlertsDialogComponent
     } from '@eg/staff/share/holdings/copy-alerts-dialog.component';
@@ -45,8 +44,6 @@ export class CheckoutComponent implements OnInit, AfterViewInit {
         private nonCatCount: PromptDialogComponent;
     @ViewChild('checkoutsGrid')
         private checkoutsGrid: GridComponent;
-    @ViewChild('precatDialog')
-        private precatDialog: PrecatCheckoutDialogComponent;
     @ViewChild('copyAlertsDialog')
         private copyAlertsDialog: CopyAlertsDialogComponent;
     @ViewChild('barcodeSelect')
@@ -158,18 +155,11 @@ export class CheckoutComponent implements OnInit, AfterViewInit {
     }
 
     dispatchResult(result: CheckoutResult) {
-
         if (result.success) {
             this.gridifyResult(result);
             this.resetForm();
             return;
         }
-
-        switch (result.evt.textcode) {
-            case 'ITEM_NOT_CATALOGED':
-                this.handlePrecat(result);
-                break;
-        }
     }
 
     resetForm() {
@@ -278,17 +268,6 @@ export class CheckoutComponent implements OnInit, AfterViewInit {
         }
     }
 
-    handlePrecat(result: CheckoutResult) {
-        this.precatDialog.open().subscribe(values => {
-            if (values && values.dummy_title) {
-                const params = result.params;
-                params.precat = true;
-                Object.keys(values).forEach(key => params[key] = values[key]);
-                this.checkout(params);
-            }
-        });
-    }
-
     selectedCopyIds(rows: CircGridEntry[]): number[] {
         return rows
             .filter(row => row.copy)
index 798148c..f917cbb 100644 (file)
@@ -4,6 +4,8 @@
   </eg-staff-banner>
 </ng-container>
 
+<eg-circ-components></eg-circ-components>
+
 <ng-container *ngIf="context.patron">
   <eg-staff-banner i18n-bannerText bannerText="
     {{patronService.namePart(context.patron, 'family_name')}}, 
index e9b1050..caaebbc 100644 (file)
@@ -6,10 +6,12 @@ import {CircGridComponent} from './grid.component';
 import {DueDateDialogComponent} from './due-date-dialog.component';
 import {PrecatCheckoutDialogComponent} from './precat-dialog.component';
 import {ClaimsReturnedDialogComponent} from './claims-returned-dialog.component';
+import {CircComponentsComponent} from './components.component';
 
 @NgModule({
     declarations: [
         CircGridComponent,
+        CircComponentsComponent,
         DueDateDialogComponent,
         PrecatCheckoutDialogComponent,
         ClaimsReturnedDialogComponent
@@ -20,7 +22,7 @@ import {ClaimsReturnedDialogComponent} from './claims-returned-dialog.component'
     ],
     exports: [
         CircGridComponent,
-        PrecatCheckoutDialogComponent
+        CircComponentsComponent
     ],
     providers: [
         CircService
index 3bcaa29..f1e7530 100644 (file)
@@ -9,11 +9,13 @@ import {EventService, EgEvent} from '@eg/core/event.service';
 import {AuthService} from '@eg/core/auth.service';
 import {BibRecordService, BibRecordSummary} from '@eg/share/catalog/bib-record.service';
 import {AudioService} from '@eg/share/util/audio.service';
+import {PrecatCheckoutDialogComponent
+    } from '@eg/staff/share/circ/precat-dialog.component';
 
 
 // API parameter options
 export interface CheckoutParams {
-    patron_id: number;
+    patron_id?: number;
     due_date?: string;
     copy_id?: number;
     copy_barcode?: string;
@@ -33,9 +35,10 @@ export interface CheckoutResult {
     evt: EgEvent;
     params: CheckoutParams;
     success: boolean;
+    canceled?: boolean;
     copy?: IdlObject;
     circ?: IdlObject;
-    nonCatCirc: IdlObject;
+    nonCatCirc?: IdlObject;
     record?: IdlObject;
 }
 
@@ -61,6 +64,7 @@ export class CircService {
     static resultIndex = 0;
 
     nonCatTypes: IdlObject[] = null;
+    precatDialog: PrecatCheckoutDialogComponent;
 
     constructor(
         private audio: AudioService,
@@ -98,6 +102,19 @@ export class CircService {
         .then(result => this.processCheckoutResult(params, result));
     }
 
+    renew(params: CheckoutParams, override?: boolean): Promise<CheckoutResult> {
+
+        console.debug('renewing out with', params);
+
+        let method = 'open-ils.circ.renew';
+        if (override) { method += '.override'; }
+
+        return this.net.request(
+            'open-ils.circ', method,
+            this.auth.token(), params).toPromise()
+        .then(result => this.processCheckoutResult(params, result));
+    }
+
     processCheckoutResult(
         params: CheckoutParams, response: any): Promise<CheckoutResult> {
 
@@ -124,9 +141,31 @@ export class CircService {
             nonCatCirc: payload.noncat_circ
         };
 
+        switch (evt.textcode) {
+            case 'ITEM_NOT_CATALOGED':
+                return this.handlePrecat(result);
+        }
+
         return Promise.resolve(result);
     }
 
+    handlePrecat(result: CheckoutResult): Promise<CheckoutResult> {
+        this.precatDialog.barcode = result.params.copy_barcode;
+
+        return this.precatDialog.open().toPromise().then(values => {
+
+            if (values && values.dummy_title) {
+                const params = result.params;
+                params.precat = true;
+                Object.keys(values).forEach(key => params[key] = values[key]);
+                return this.checkout(params);
+            }
+
+            result.canceled = true;
+            return Promise.resolve(result);
+        });
+    }
+
     checkin(params: CheckinParams, override?: boolean): Promise<CheckinResult> {
 
         console.debug('checking in with', params);
@@ -161,11 +200,14 @@ export class CircService {
                 // alert, etc.
         }
 
+        const success =
+            evt.textcode.match(/SUCCESS|NO_CHANGE|ROUTE_ITEM/) !== null;
+
         const result: CheckinResult = {
             index: CircService.resultIndex++,
             evt: evt,
             params: params,
-            success: evt.textcode === 'SUCCESS', // or route, no change, etc.
+            success: success,
             circ: payload.circ,
             copy: payload.copy,
             record: payload.record
@@ -176,6 +218,35 @@ export class CircService {
 
     // The provided params (minus the copy_id) will be used
     // for all items.
+    checkoutBatch(copyIds: number[], params: CheckoutParams): Observable<CheckoutResult> {
+        if (copyIds.length === 0) { return empty(); }
+        const source = from(copyIds);
+
+        return source.pipe(concatMap(id => {
+            const cparams = Object.assign(params, {}); // clone
+            cparams.copy_id = id;
+            return from(this.checkout(cparams));
+        }));
+    }
+
+    // The provided params (minus the copy_id) will be used
+    // for all items.
+    renewBatch(copyIds: number[], params?: CheckoutParams): Observable<CheckoutResult> {
+        if (copyIds.length === 0) { return empty(); }
+
+        if (!params) { params = {}; }
+
+        const source = from(copyIds);
+
+        return source.pipe(concatMap(id => {
+            const cparams = Object.assign(params, {}); // clone
+            cparams.copy_id = id;
+            return from(this.renew(cparams));
+        }));
+    }
+
+    // The provided params (minus the copy_id) will be used
+    // for all items.
     checkinBatch(copyIds: number[], params?: CheckinParams): Observable<CheckinResult> {
         if (copyIds.length === 0) { return empty(); }
 
diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html b/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html
new file mode 100644 (file)
index 0000000..06641e3
--- /dev/null
@@ -0,0 +1,4 @@
+
+<eg-precat-checkout-dialog #precatDialog></eg-precat-checkout-dialog>
+
+
diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts b/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts
new file mode 100644 (file)
index 0000000..0568025
--- /dev/null
@@ -0,0 +1,28 @@
+import {Component, AfterViewInit, Output, Input, ViewChild, EventEmitter} from '@angular/core';
+import {CircService} from './circ.service';
+import {PrecatCheckoutDialogComponent
+    } from '@eg/staff/share/circ/precat-dialog.component';
+
+/* Container component for sub-components used by circulation actions.
+ *
+ * The CircService has to launch various dialogs for processing checkouts,
+ * checkins, etc.  The service itself cannot contain components directly,
+ * so we compile them here and provide references.
+ * */
+
+@Component({
+  templateUrl: 'components.component.html',
+  selector: 'eg-circ-components'
+})
+export class CircComponentsComponent implements AfterViewInit {
+
+    @ViewChild('precatDialog')
+        private precatDialog: PrecatCheckoutDialogComponent;
+
+    constructor(private circ: CircService) {}
+
+    ngAfterViewInit() {
+        this.circ.precatDialog = this.precatDialog;
+    }
+}
+
index df19104..ab596df 100644 (file)
     (onClick)="markLost($event)"></eg-grid-toolbar-action>
 
   <!-- .subscribe() nudges the observable to run -->
-  <eg-grid-toolbar-action i18n-label label="Checkin" 
+  <eg-grid-toolbar-action 
+    group="Circulation" i18n-group i18n-label label="Checkin" 
     (onClick)="checkin($event).subscribe()">
   </eg-grid-toolbar-action>
 
+  <eg-grid-toolbar-action group="Circulation" i18n-group 
+    i18n-label label="Renew" (onClick)="renew($event)">
+  </eg-grid-toolbar-action>
+
   <eg-grid-column [index]="true" path="index" [hidden]="true"
     label="Row Index" i18n-label></eg-grid-column>
 
index 32393fb..b2a5ab2 100644 (file)
@@ -410,6 +410,22 @@ export class CircGridComponent implements OnInit {
         return this.progressDialog;
     }
 
+    renew(rows: CircGridEntry[]) {
+
+        const dialog = this.openProgressDialog(rows);
+        const params: CheckoutParams = {};
+
+        return this.circ.renewBatch(this.getCopyIds(rows))
+        .subscribe(
+            result => dialog.increment(),
+            err => console.error(err),
+            () => {
+                dialog.close();
+                this.emitReloadRequest();
+            }
+        );
+    }
+
     // Same params will be used for each copy
     checkin(rows: CircGridEntry[], params?:
         CheckinParams, noReload?: boolean): Observable<CheckinResult> {