LP1904036 waivers; more checkin
authorBill Erickson <berickxx@gmail.com>
Fri, 9 Apr 2021 01:45:35 +0000 (21:45 -0400)
committerGalen Charlton <gmc@equinoxOLI.org>
Fri, 28 Oct 2022 00:13:30 +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/items.component.html
Open-ILS/src/eg2/src/app/staff/share/circ/circ.service.ts
Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html
Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts
Open-ILS/src/eg2/src/app/staff/share/patron/summary.component.html

index ab5b137..6ef7700 100644 (file)
                                (onClick)="openItemAlerts($event, 'create')">
                        </eg-grid-toolbar-action>
 
+                       <eg-grid-toolbar-action
+                               i18n-group group="Add" i18n-label label="Manage Item Alerts"
+        [disabled]="checkoutsGrid.context.rowSelector.selected().length !== 1"
+                               (onClick)="openItemAlerts($event, 'manage')">
+                       </eg-grid-toolbar-action>
+
       <eg-grid-column path="index" [index]="true" 
         label="Row Index" i18n-label [hidden]="true"></eg-grid-column>
       <eg-grid-column path="circ.id" label="Circ ID" i18n-label></eg-grid-column>
index 0e262f3..124ef24 100644 (file)
@@ -287,8 +287,7 @@ export class CheckoutComponent implements OnInit, AfterViewInit {
         this.copyAlertsDialog.open({size: 'lg'}).subscribe(
             modified => {
                 if (modified) {
-                    // TODO: verify the modiifed alerts are present
-                    // or go fetch them.
+                    rows.forEach(row => row.copyAlertCount++);
                     this.checkoutsGrid.reload();
                 }
             }
index 2206f06..2dc6907 100644 (file)
@@ -35,7 +35,7 @@
     </ng-container>
     <li ngbNavItem="noncat">
       <a ngbNavLink i18n>
-        <ng-container *ngIf="context.summary.stats">
+        <ng-container *ngIf="context.summary && context.summary.stats">
           Non-Cataloged Circulations ({{context.summary.stats.checkouts.noncat}})
         </ng-container>
       </a>
index b5dbcfd..eb9e5ba 100644 (file)
@@ -11,6 +11,7 @@ import {BibRecordService, BibRecordSummary} from '@eg/share/catalog/bib-record.s
 import {AudioService} from '@eg/share/util/audio.service';
 import {CircEventsComponent} from './events-dialog.component';
 import {CircComponentsComponent} from './components.component';
+import {StringService} from '@eg/share/string/string.service';
 
 export interface CircDisplayInfo {
     title?: string;
@@ -171,6 +172,7 @@ export class CircService {
     autoOverrideCheckoutEvents: {[textcode: string]: boolean} = {};
     suppressCheckinPopups = false;
     ignoreCheckinPrecats = false;
+    copyLocationCache: {[id: number]: IdlObject} = {};
 
     constructor(
         private audio: AudioService,
@@ -178,6 +180,7 @@ export class CircService {
         private org: OrgService,
         private net: NetService,
         private pcrud: PcrudService,
+        private strings: StringService,
         private auth: AuthService,
         private bib: BibRecordService,
     ) {}
@@ -451,12 +454,11 @@ export class CircService {
         return this.net.request(
             'open-ils.circ', method,
             this.auth.token(), this.apiParams(params)).toPromise()
-        .then(result => this.processCheckinResult(params, result));
+        .then(result => this.unpackCheckinData(params, result))
+        .then(result => this.processCheckinResult(result));
     }
 
-    processCheckinResult(
-        params: CheckinParams, response: any): Promise<CheckinResult> {
-
+    unpackCheckinData(params: CheckinParams, response: any): Promise<CheckinResult> {
         const allEvents = Array.isArray(response) ?
             response.map(r => this.evt.parse(r)) : [this.evt.parse(response)];
 
@@ -476,7 +478,7 @@ export class CircService {
         const result: CheckinResult = {
             index: CircService.resultIndex++,
             firstEvent: firstEvent,
-            allEvents: response,
+            allEvents: allEvents,
             params: params,
             success: success,
             circ: payload.circ,
@@ -484,6 +486,28 @@ export class CircService {
             record: payload.record
         };
 
+        let promise = Promise.resolve();;
+        const copy = result.copy;
+
+        if (copy) {
+            if (this.copyLocationCache[copy.location()]) {
+                copy.location(this.copyLocationCache[copy.location()]);
+            } else {
+                promise = this.pcrud.retrieve('acpl', copy.location()).toPromise()
+                .then(loc => {
+                    copy.location(loc);
+                    this.copyLocationCache[loc.id()] = loc;
+                });
+            }
+        }
+
+        return promise.then(_ => result);
+    }
+
+    processCheckinResult(result: CheckinResult): Promise<CheckinResult> {
+        const params = result.params;
+        const allEvents = result.allEvents;
+
         // Informational alerts that can be ignored if configured.
         if (this.suppressCheckinPopups &&
             allEvents.filter(e =>
@@ -507,10 +531,9 @@ export class CircService {
             return this.showOverrideDialog(result, allEvents, true);
         }
 
-        switch (firstEvent.textcode) {
+        switch (result.firstEvent.textcode) {
             case 'SUCCESS':
             case 'NO_CHANGE':
-                this.audio.play('success.checkin');
                 return this.handleCheckinSuccess(result);
 
             case 'ITEM_NOT_CATALOGED':
@@ -527,9 +550,37 @@ export class CircService {
     }
 
     handleCheckinSuccess(result: CheckinResult): Promise<CheckinResult> {
+
+        switch (result.copy.status()) {
+
+            case 0: /* AVAILABLE */
+            case 4: /* MISSING */
+            case 7: /* RESHELVING */
+                this.audio.play('success.checkin');
+                return this.handleCheckinLocAlert(result);
+        }
+
         return Promise.resolve(result);
     }
 
+    handleCheckinLocAlert(result: CheckinResult): Promise<CheckinResult> {
+        const copy = result.copy;
+
+        if (this.suppressCheckinPopups
+            || copy.location().checkin_alert() === 'f') {
+            return Promise.resolve(result);
+        }
+
+        return this.strings.interpolate(
+            'staff.circ.checkin.location.alert',
+            {barcode: copy.barcode(), location: copy.location().name()}
+        ).then(str => {
+            this.components.locationAlertDialog.dialogBody = str;
+            return this.components.locationAlertDialog.open().toPromise()
+            .then(_ => result);
+        });
+    }
+
     handleOverridableCheckinEvents(
         result: CheckinResult, events: EgEvent[]): Promise<CheckinResult> {
         const params = result.params;
@@ -539,7 +590,6 @@ export class CircService {
             // Should never get here.  Just being safe.
             return Promise.reject(null);
         }
-
     }
 
 
index 9afc0ef..c287856 100644 (file)
@@ -8,6 +8,15 @@
   i18n-dialogBody dialogBody="This item needs to be routed to CATALOGING">
 </eg-alert-dialog>
 
+<eg-string key="staff.circ.checkin.location.alert"
+  i18n-text text="Item {{barcode}} needs to be routed to {{location}}">
+</eg-string>
+
+<!-- dialogBody is generated dynamically from string above -->
+
+<eg-alert-dialog #locationAlertDialog i18n-dialogTitle dialogTitle="Route Item">
+</eg-alert-dialog>
+
 <eg-open-circ-dialog #openCircDialog></eg-open-circ-dialog>
 
 
index 3808ca9..d1bcadb 100644 (file)
@@ -23,6 +23,7 @@ export class CircComponentsComponent {
     @ViewChild('circEventsDialog') circEventsDialog: CircEventsComponent;
     @ViewChild('routeToCatalogingDialog') routeToCatalogingDialog: AlertDialogComponent;
     @ViewChild('openCircDialog') openCircDialog: OpenCircDialogComponent;
+    @ViewChild('locationAlertDialog') locationAlertDialog: AlertDialogComponent;
 
     constructor(private circ: CircService) {
         this.circ.components = this;
index 931662f..5f5251c 100644 (file)
   <div class="row mb-1">
     <div class="col-lg-5" i18n>Email</div>
     <div class="col-lg-7">
-      <!-- TODO: mailto link -->
-      {{p().email()}}
+      <a *ngIf="p().email()" href="mailto:{{p().email()}}">{{p().email()}}</a>
     </div> 
   </div>
+  <div class="row mb-1" *ngIf="p().name_keywords()">
+    <div class="col-lg-5" i18n>Name Keywords</div>
+    <div class="col-lg-7">{{p().name_keywords()}}</div> 
+  </div>
+
+  <ng-container *ngIf="p().waiver_entries().length">
+    <hr class="m-1"/>
+    <div class="row mb-1 alert alert-info p-0">
+      <div class="col-lg-12" i18n>Allow others to use my account</div>
+    </div>
+    <div class="row mb-1" *ngFor="let waiver of p().waiver_entries()">
+      <div class="col-lg-5" i18n>{{waiver.name()}}</div>
+      <div class="col-lg-7">
+        <ul>
+          <li *ngIf="waiver.place_holds() == 't'" i18n>Place holds</li>
+          <li *ngIf="waiver.pickup_holds() == 't'" i18n>Pick up holds</li>
+          <li *ngIf="waiver.view_history() == 't'" i18n>View borrowing history</li>
+          <li *ngIf="waiver.checkout_items() == 't'" i18n>Check out items</li>
+        </ul>
+      </div>
+    </div>
+  </ng-container>
 
   <hr class="m-1"/>