LP1840773 SCKO Angular
authorBill Erickson <berickxx@gmail.com>
Tue, 28 Jun 2022 15:16:11 +0000 (11:16 -0400)
committerBill Erickson <berickxx@gmail.com>
Tue, 28 Jun 2022 15:16:11 +0000 (11:16 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/scko/scko.component.html
Open-ILS/src/eg2/src/app/scko/scko.service.ts

index f817261..9b9525c 100644 (file)
@@ -5,6 +5,8 @@
 <eg-string i18n-text key="scko.renew.success" text="Renewal Succeeded"></eg-string>
 <eg-string i18n-text key="scko.item.not_found" 
   text="Item was not found in the system. Try re-scanning the item."></eg-string>
+<eg-string i18n-text key="scko.checkout.already_out" 
+  text="Item is checked out to another patron"></eg-string>
 
 <div class="d-flex">
   <div class="flex-1"></div>
index e0109f0..f6e4a09 100644 (file)
@@ -21,6 +21,7 @@ interface CheckoutStat {
     displayTextArgs: any;
     alertSound: string;
     shouldPopup: boolean;
+    previousCirc?: number;
 }
 
 @Injectable({providedIn: 'root'})
@@ -38,6 +39,8 @@ export class SckoService {
 
     alertAudio = false;
     alertPopup = false;
+    orgSettings: any;
+    overrideCheckoutEvents: string[] = [];
 
     sessionCheckouts: any[] = [];
 
@@ -92,6 +95,8 @@ export class SckoService {
             ]);
 
         }).then(sets => {
+            this.orgSettings = sets;
+
             const regPattern = sets['opac.barcode_regex'] || /^\d/;
             this.barcodeRegex = new RegExp(regPattern);
             this.patronPasswordRequired =
@@ -100,6 +105,9 @@ export class SckoService {
             this.alertAudio = sets['circ.selfcheck.alert.sound'];
             this.alertPopup = sets['circ.selfcheck.alert.popup'];
 
+            this.overrideCheckoutEvents =
+                sets['circ.selfcheck.auto_override_checkout_events'] || [];
+
             this.patronIdleTimeout =
                 Number(sets['circ.selfcheck.patron_login_timeout'] || 160);
 
@@ -333,10 +341,105 @@ export class SckoService {
         if (evt.textcode === 'SUCCESS') {
             checkoutStat.displayText = `scko.${action}.success`;
             checkoutStat.alertSound = `success.scko.${action}`;
+            return Promise.resolve(checkoutStat);
+        }
+
+        if (evt.textcode === 'OPEN_CIRCULATION_EXISTS' && action === 'checkout') {
+            return this.handleOpenCirc(checkoutStat, payload, barcode);
         }
 
         return Promise.resolve(checkoutStat);
     }
+
+    handleOpenCirc(stat: CheckoutStat, payload: any, barcode: string): Promise<any> {
+
+        if (payload.old_circ) {
+            const age = this.orgSettings['circ.checkout_auto_renew_age'];
+
+            if (!age || (age && payload.auto_renew)) {
+                stat.previousCirc = Number(payload.old_circ.id());
+                stat.renew = true;
+                return Promise.resolve(stat);
+            }
+        }
+
+        // LOST items can be checked in and made usable if configured.
+        if (payload.copy
+            && Number(payload.copy.status()) === /* LOST */ 3
+            && this.overrideCheckoutEvents.length
+            && this.overrideCheckoutEvents.includes('COPY_STATUS_LOST')) {
+
+            return this.checkin(barcode).then(ok => {
+                if (ok) {
+                    stat.redo = true;
+                } else {
+                    stat.shouldPopup = true;
+                    stat.alertSound = 'error.scko.checkout';
+                    stat.displayText = 'scko.checkout.already_out';
+                }
+
+                return stat;
+            });
+        }
+
+        stat.shouldPopup = true;
+        stat.alertSound = 'error.scko.checkout';
+        stat.displayText = 'scko.checkout.already_out';
+
+        return Promise.resolve(stat);
+    }
+
+    checkin(barcode: string, abortTransit?: boolean): Promise<boolean> {
+
+        let promise = Promise.resolve(true);
+
+        if (abortTransit) {
+
+            promise = this.net.request(
+                'open-ils.circ',
+                'open-ils.circ.transit.abort',
+                this.auth.token(), {barcode: barcode}).toPromise()
+
+            .then(resp => {
+
+                console.debug('Transit abort returned', resp);
+                return Number(resp) === 1;
+            });
+        }
+
+        promise = promise.then(ok => {
+            if (!ok) { return false; }
+
+            return this.net.request(
+                'open-ils.circ',
+                'open-ils.circ.checkin.override',
+                this.auth.token(), {
+                    patron_id : this.patronSummary.id,
+                    copy_barcode : barcode,
+                    noop : true
+                }
+
+            ).toPromise().then(resp => {
+
+                // If any response events are non-success, report the
+                // checkin as a failure.
+                let success = true;
+                [].concat(resp).forEach(evt => {
+                    console.debug('Checkin returned', resp);
+
+                    const code = evt.textcode;
+                    if (code !== 'SUCCESS' && code !== 'NO_CHANGE') {
+                        success = false;
+                    }
+                });
+
+                return success;
+
+            });
+        });
+
+        return promise;
+    }
 }