this.modifiers.noop = false;
this.modifiers.auto_print_holds_transits = true;
}
-
- });
+ }).then(_ => this.circ.applySettings());
}
ngAfterViewInit() {
import {CopyInTransitDialogComponent} from './in-transit-dialog.component';
import {CancelTransitDialogComponent} from './cancel-transit-dialog.component';
import {BackdateDialogComponent} from './backdate-dialog.component';
+import {WorkLogService} from './work-log.service';
@NgModule({
declarations: [
CircComponentsComponent
],
providers: [
- CircService
+ CircService,
+ WorkLogService
]
})
import {StringService} from '@eg/share/string/string.service';
import {ServerStoreService} from '@eg/core/server-store.service';
import {HoldingsService} from '@eg/staff/share/holdings/holdings.service';
+import {WorkLogService, WorkLogEntry} from './work-log.service';
export interface CircDisplayInfo {
title?: string;
private strings: StringService,
private auth: AuthService,
private holdings: HoldingsService,
+ private worklog: WorkLogService,
private bib: BibRecordService
) {}
'circ.clear_hold_on_checkout',
]).then(sets => {
this.clearHoldsOnCheckout = sets['circ.clear_hold_on_checkout'];
+ return this.worklog.loadSettings();
});
}
result.record = payload.record;
result.nonCatCirc = payload.noncat_circ;
- return this.fleshCommonData(result);
+ return this.fleshCommonData(result).then(_ => {
+ this.addWorkLog(params._renewal ? 'renewal' : 'checkout', result);
+ return result;
+ });
}
processCheckoutResult(result: CheckoutResult): Promise<CheckoutResult> {
result.mbts = parent_circ.billable_transaction().summary();
}
- return this.fleshCommonData(result).then(_ => result);
+ return this.fleshCommonData(result).then(_ => {
+ this.addWorkLog('checkin', result);
+ return result;
+ });
}
processCheckinResult(result: CheckinResult): Promise<CheckinResult> {
return Promise.resolve(result);
}
+ addWorkLog(action: string, result: CircResultCommon) {
+ const entry: WorkLogEntry = {action: action};
+
+ const params = result.params;
+ const copy = result.copy;
+ const patron = result.patron;
+
+ if (copy) {
+ entry.item = copy.barcode();
+ entry.item_id = copy.id();
+ } else {
+ entry.item = params.copy_barcode;
+ entry.item_id = params.copy_id;
+ }
+
+ if (patron) {
+ entry.patron_id = patron.id();
+ entry.user = patron.family_name();
+ } else {
+ entry.patron_id = (params as CheckoutParams).patron_id;
+ }
+
+ if (result.hold) {
+ entry.hold_id = result.hold.id();
+ }
+
+ this.worklog.record(entry);
+ }
+
showPrecatAlert(): Promise<any> {
if (!this.suppressCheckinPopups && !this.ignoreCheckinPrecats) {
// Tell the user its a precat and return the result.
<eg-copy-alert-manager #copyAlertManager></eg-copy-alert-manager>
+<!-- Worklog string identifiers should match #worlog_{{action}} -->
+<eg-string #worklog_checkout i18n-text text="Check Out"></eg-string>
+<eg-string #worklog_checkin i18n-text text="Check In"></eg-string>
+<eg-string #worklog_noncat_checkout i18n-text text="Noncataloged Checkout"></eg-string>
+<eg-string #worklog_renew i18n-text text="Renewal"></eg-string>
+<eg-string #worklog_requested_hold i18n-text text="Requested Hold"></eg-string>
+<eg-string #worklog_edited_patron i18n-text text="Edited Patron"></eg-string>
+<eg-string #worklog_registered_patron i18n-text text="Registered Patron"></eg-string>
+<eg-string #worklog_paid_bill i18n-text text="Paid Bill"></eg-string>
+
import {CopyInTransitDialogComponent} from './in-transit-dialog.component';
import {CopyAlertManagerDialogComponent
} from '@eg/staff/share/holdings/copy-alert-manager.component';
+import {WorkLogService, WorkLogEntry} from './work-log.service';
/* Container component for sub-components used by circulation actions.
*
@ViewChild('holdShelfStr') holdShelfStr: StringComponent;
@ViewChild('catalogingStr') catalogingStr: StringComponent;
- constructor(private circ: CircService) {
+ // Worklog string variable names have to match "worklog_{{action}}"
+ @ViewChild('worklog_checkout') worklog_checkout: StringComponent;
+ @ViewChild('worklog_checkin') worklog_checkin: StringComponent;
+ @ViewChild('worklog_noncat_checkout') worklog_noncat_checkout: StringComponent;
+ @ViewChild('worklog_renew') worklog_renew: StringComponent;
+ @ViewChild('worklog_requested_hold') worklog_requested_hold: StringComponent;
+ @ViewChild('worklog_edited_patron') worklog_edited_patron: StringComponent;
+ @ViewChild('worklog_registered_patron') worklog_registered_patron: StringComponent;
+ @ViewChild('worklog_paid_bill') worklog_paid_bill: StringComponent;
+
+ constructor(
+ private worklog: WorkLogService,
+ private circ: CircService) {
this.circ.components = this;
+ this.worklog.components = this;
}
}
--- /dev/null
+import {Injectable} from '@angular/core';
+import {Observable, empty, from} from 'rxjs';
+import {map, concatMap, mergeMap} from 'rxjs/operators';
+import {IdlObject} from '@eg/core/idl.service';
+import {NetService} from '@eg/core/net.service';
+import {OrgService} from '@eg/core/org.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+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 {CircEventsComponent} from './events-dialog.component';
+import {CircComponentsComponent} from './components.component';
+import {StringService} from '@eg/share/string/string.service';
+import {ServerStoreService} from '@eg/core/server-store.service';
+import {StoreService} from '@eg/core/store.service';
+import {HoldingsService} from '@eg/staff/share/holdings/holdings.service';
+
+export interface WorkLogEntry {
+ when?: Date;
+ msg?: string;
+ action?: string;
+ actor?: string // staff username
+ item?: string; // barcode
+ item_id?: number;
+ user?: string; // patron family name
+ patron_id?: number;
+ hold_id?: number;
+ amount?: number; // paid amount
+}
+
+
+@Injectable()
+export class WorkLogService {
+
+ maxEntries: number = null;
+ maxPatrons: number = null;
+ components: CircComponentsComponent;
+
+ constructor(
+ private store: StoreService,
+ private serverStore: ServerStoreService,
+ private auth: AuthService
+ ) {}
+
+ loadSettings(): Promise<any> {
+ return this.serverStore.getItemBatch([
+ 'ui.admin.work_log.max_entries',
+ 'ui.admin.patron_log.max_entries'
+ ]).then(sets => {
+ this.maxEntries = sets['ui.admin.work_log.max_entries'] || 20;
+ this.maxPatrons = sets['ui.admin.patron_log.max_entries'] || 10;
+ });
+ }
+
+ record(entry: WorkLogEntry) {
+
+ if (this.maxEntries === null) {
+ throw new Error('WorkLogService.loadSettings() required');
+ return;
+ }
+
+ entry.when = new Date();
+ entry.actor = this.auth.user().usrname();
+ entry.msg = this.components[`worklog_${entry.action}`].text;
+
+ const workLog = this.store.getLocalItem('eg.work_log') || [];
+ let patronLog = this.store.getLocalItem('eg.patron_log') || [];
+
+ workLog.push(entry);
+ if (workLog.lenth > this.maxEntries) {
+ workLog.shift();
+ }
+
+ console.log('HERE', workLog);
+
+ this.store.setLocalItem('eg.work_log', workLog);
+
+ if (entry.patron_id) {
+ // Remove existing entries that match this patron
+ patronLog = patronLog.filter(e => e.patron_id !== entry.patron_id);
+
+ patronLog.push(entry);
+ if (patronLog.length > this.maxPatrons) {
+ patronLog.shift();
+ }
+
+ this.store.setLocalItem('eg.patron_log', patronLog);
+ }
+ }
+}
+
+