LP1904036 Renew all; initial events override dialog
authorBill Erickson <berickxx@gmail.com>
Fri, 26 Feb 2021 23:17:06 +0000 (18:17 -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/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
Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts
Open-ILS/src/eg2/src/app/staff/share/circ/events-dialog.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/share/circ/events-dialog.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 caaebbc..a067588 100644 (file)
@@ -7,6 +7,7 @@ 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';
+import {CircEventsComponent} from './events-dialog.component';
 
 @NgModule({
     declarations: [
@@ -14,7 +15,8 @@ import {CircComponentsComponent} from './components.component';
         CircComponentsComponent,
         DueDateDialogComponent,
         PrecatCheckoutDialogComponent,
-        ClaimsReturnedDialogComponent
+        ClaimsReturnedDialogComponent,
+        CircEventsComponent
     ],
     imports: [
         StaffCommonModule,
index f1e7530..1146029 100644 (file)
@@ -9,8 +9,91 @@ 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';
+import {CircEventsComponent} from './events-dialog.component';
+import {CircComponentsComponent} from './components.component';
+
+
+const CAN_OVERRIDE_CHECKOUT_EVENTS = [
+       'PATRON_EXCEEDS_OVERDUE_COUNT',
+       'PATRON_EXCEEDS_CHECKOUT_COUNT',
+       'PATRON_EXCEEDS_FINES',
+       'PATRON_EXCEEDS_LONGOVERDUE_COUNT',
+       'PATRON_BARRED',
+       'CIRC_EXCEEDS_COPY_RANGE',
+       'ITEM_DEPOSIT_REQUIRED',
+       'ITEM_RENTAL_FEE_REQUIRED',
+       'PATRON_EXCEEDS_LOST_COUNT',
+       'COPY_CIRC_NOT_ALLOWED',
+       'COPY_NOT_AVAILABLE',
+       'COPY_IS_REFERENCE',
+       'COPY_ALERT_MESSAGE',
+       'ITEM_ON_HOLDS_SHELF',
+       'STAFF_C',
+       'STAFF_CH',
+       'STAFF_CHR',
+       'STAFF_CR',
+       'STAFF_H',
+       'STAFF_HR',
+       'STAFF_R'
+];
+
+const CHECKOUT_OVERRIDE_AFTER_FIRST = [
+    'PATRON_EXCEEDS_OVERDUE_COUNT',
+    'PATRON_BARRED',
+    'PATRON_EXCEEDS_LOST_COUNT',
+    'PATRON_EXCEEDS_CHECKOUT_COUNT',
+    'PATRON_EXCEEDS_FINES',
+    'PATRON_EXCEEDS_LONGOVERDUE_COUNT'
+];
+
+const CAN_OVERRIDE_RENEW_EVENTS = [
+    'PATRON_EXCEEDS_OVERDUE_COUNT',
+    'PATRON_EXCEEDS_LOST_COUNT',
+    'PATRON_EXCEEDS_CHECKOUT_COUNT',
+    'PATRON_EXCEEDS_FINES',
+    'PATRON_EXCEEDS_LONGOVERDUE_COUNT',
+    'CIRC_EXCEEDS_COPY_RANGE',
+    'ITEM_DEPOSIT_REQUIRED',
+    'ITEM_RENTAL_FEE_REQUIRED',
+    'ITEM_DEPOSIT_PAID',
+    'COPY_CIRC_NOT_ALLOWED',
+    'COPY_NOT_AVAILABLE',
+    'COPY_IS_REFERENCE',
+    'COPY_ALERT_MESSAGE',
+    'COPY_NEEDED_FOR_HOLD',
+    'MAX_RENEWALS_REACHED',
+    'CIRC_CLAIMS_RETURNED',
+    'STAFF_C',
+    'STAFF_CH',
+    'STAFF_CHR',
+    'STAFF_CR',
+    'STAFF_H',
+    'STAFF_HR',
+    'STAFF_R'
+]
+
+// These checkin events do not produce alerts when
+// options.suppress_alerts is in effect.
+const CAN_SUPPRESS_CHECKIN_ALERTS = [
+       'COPY_BAD_STATUS',
+       'PATRON_BARRED',
+       'PATRON_INACTIVE',
+       'PATRON_ACCOUNT_EXPIRED',
+       'ITEM_DEPOSIT_PAID',
+       'CIRC_CLAIMS_RETURNED',
+       'COPY_ALERT_MESSAGE',
+       'COPY_STATUS_LOST',
+       'COPY_STATUS_LOST_AND_PAID',
+       'COPY_STATUS_LONG_OVERDUE',
+       'COPY_STATUS_MISSING',
+       'PATRON_EXCEEDS_FINES'
+];
+
+const CAN_OVERRIDE_CHECKIN_ALERTS = [
+    // not technically overridable, but special prompt and param
+       'HOLD_CAPTURE_DELAYED',
+       'TRANSIT_CHECKIN_INTERVAL_BLOCK'
+].concat(CAN_SUPPRESS_CHECKIN_ALERTS);
 
 
 // API parameter options
@@ -63,8 +146,8 @@ export interface CheckinResult {
 export class CircService {
     static resultIndex = 0;
 
+    components: CircComponentsComponent;
     nonCatTypes: IdlObject[] = null;
-    precatDialog: PrecatCheckoutDialogComponent;
 
     constructor(
         private audio: AudioService,
@@ -150,9 +233,9 @@ export class CircService {
     }
 
     handlePrecat(result: CheckoutResult): Promise<CheckoutResult> {
-        this.precatDialog.barcode = result.params.copy_barcode;
+        this.components.precatDialog.barcode = result.params.copy_barcode;
 
-        return this.precatDialog.open().toPromise().then(values => {
+        return this.components.precatDialog.open().toPromise().then(values => {
 
             if (values && values.dummy_title) {
                 const params = result.params;
index 06641e3..1ec9fa4 100644 (file)
@@ -1,4 +1,4 @@
 
 <eg-precat-checkout-dialog #precatDialog></eg-precat-checkout-dialog>
-
+<eg-circ-events-dialog #eventDialog></eg-circ-events-dialog>
 
index 0568025..1d8cc15 100644 (file)
@@ -1,7 +1,7 @@
-import {Component, AfterViewInit, Output, Input, ViewChild, EventEmitter} from '@angular/core';
+import {Component, OnInit, Output, Input, ViewChild, EventEmitter} from '@angular/core';
 import {CircService} from './circ.service';
-import {PrecatCheckoutDialogComponent
-    } from '@eg/staff/share/circ/precat-dialog.component';
+import {PrecatCheckoutDialogComponent} from './precat-dialog.component';
+import {CircEventsComponent} from './events-dialog.component';
 
 /* Container component for sub-components used by circulation actions.
  *
@@ -14,15 +14,13 @@ import {PrecatCheckoutDialogComponent
   templateUrl: 'components.component.html',
   selector: 'eg-circ-components'
 })
-export class CircComponentsComponent implements AfterViewInit {
+export class CircComponentsComponent {
 
-    @ViewChild('precatDialog')
-        private precatDialog: PrecatCheckoutDialogComponent;
+    @ViewChild('precatDialog') precatDialog: PrecatCheckoutDialogComponent;
+    @ViewChild('circEventsDialog') circEventsDialog: CircEventsComponent;
 
-    constructor(private circ: CircService) {}
-
-    ngAfterViewInit() {
-        this.circ.precatDialog = this.precatDialog;
+    constructor(private circ: CircService) {
+        this.circ.components = this;
     }
 }
 
diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/events-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/circ/events-dialog.component.html
new file mode 100644 (file)
index 0000000..19a4ba2
--- /dev/null
@@ -0,0 +1,31 @@
+
+<eg-string key="circ.events.mode.checkout" i18n-text text="Checkout"></eg-string> 
+<eg-string key="circ.events.mode.renew" i18n-text text="Renewal"></eg-string> 
+<eg-string key="circ.events.mode.checkin" i18n-text text="Checkin"></eg-string> 
+
+<ng-template #dialogContent>
+  <div class="modal-header bg-info">
+    <h4 class="modal-title">
+      <span i18n>Action Blocked</span>
+    </h4>
+    <button type="button" class="close"
+      i18n-aria-label aria-label="Close" (click)="close()">
+      <span aria-hidden="true">&times;</span>
+    </button>
+  </div>
+  <div class="modal-body">
+    <h5 i18n>Exceptions occurred during {{modeLabel}}.</h5>
+    <ng-container *ngFor="let evt of events">
+      <div class="card mb-2">
+        <div class="card-header">{{evt.textcode}}</div>
+        <div class="card-body">{{evt.desc}}</div>
+      </div>
+    </ng-container>
+  </div>
+  <div class="modal-footer">
+    <button type="button" class="btn btn-info"
+      (click)="close(true)" i18n>Force Action?</button>
+    <button type="button" class="btn btn-warning"
+      (click)="close(false)" i18n>Cancel</button>
+  </div>
+</ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/events-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/circ/events-dialog.component.ts
new file mode 100644 (file)
index 0000000..006b06b
--- /dev/null
@@ -0,0 +1,34 @@
+import {Component, OnInit, Output, Input, ViewChild, EventEmitter} from '@angular/core';
+import {CircService} from './circ.service';
+import {DialogComponent} from '@eg/share/dialog/dialog.component';
+import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
+import {EgEvent} from '@eg/core/event.service';
+import {StringService} from '@eg/share/string/string.service';
+
+/*
+ * Prompt to confirm overriding circulation events.
+ */
+
+@Component({
+  templateUrl: 'events-dialog.component.html',
+  selector: 'eg-circ-events-dialog'
+})
+export class CircEventsComponent extends DialogComponent implements OnInit {
+
+    @Input() events: EgEvent[] = [];
+    @Input() mode: 'checkout' | 'renew' | 'checkin';
+    modeLabel: string;
+
+    constructor(
+        private modal: NgbModal,
+        private strings: StringService
+    ) { super(modal); }
+
+    ngOnInit() {
+        this.onOpen$.subscribe(_ => {
+            this.strings.interpolate('circ.events.mode.' + this.mode)
+                .then(str => this.modeLabel = str);
+        });
+    }
+}
+
index ab596df..ea95618 100644 (file)
     i18n-label label="Renew" (onClick)="renew($event)">
   </eg-grid-toolbar-action>
 
+  <eg-grid-toolbar-action group="Circulation" i18n-group 
+    i18n-label label="Renew All" (onClick)="renewAll()">
+  </eg-grid-toolbar-action>
+
   <eg-grid-column [index]="true" path="index" [hidden]="true"
     label="Row Index" i18n-label></eg-grid-column>
 
index b2a5ab2..dba0088 100644 (file)
@@ -410,6 +410,11 @@ export class CircGridComponent implements OnInit {
         return this.progressDialog;
     }
 
+
+    renewAll() {
+        this.renew(this.entries);
+    }
+
     renew(rows: CircGridEntry[]) {
 
         const dialog = this.openProgressDialog(rows);