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: [
CircComponentsComponent,
DueDateDialogComponent,
PrecatCheckoutDialogComponent,
- ClaimsReturnedDialogComponent
+ ClaimsReturnedDialogComponent,
+ CircEventsComponent
],
imports: [
StaffCommonModule,
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
export class CircService {
static resultIndex = 0;
+ components: CircComponentsComponent;
nonCatTypes: IdlObject[] = null;
- precatDialog: PrecatCheckoutDialogComponent;
constructor(
private audio: AudioService,
}
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;
<eg-precat-checkout-dialog #precatDialog></eg-precat-checkout-dialog>
-
+<eg-circ-events-dialog #eventDialog></eg-circ-events-dialog>
-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.
*
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;
}
}
--- /dev/null
+
+<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">×</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>
--- /dev/null
+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);
+ });
+ }
+}
+
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>
return this.progressDialog;
}
+
+ renewAll() {
+ this.renew(this.entries);
+ }
+
renew(rows: CircGridEntry[]) {
const dialog = this.openProgressDialog(rows);